diff --git a/packages/metro-config/package.json b/packages/metro-config/package.json index 14b6e369f1..fdc6fe5acf 100644 --- a/packages/metro-config/package.json +++ b/packages/metro-config/package.json @@ -19,13 +19,13 @@ "license": "MIT", "dependencies": { "connect": "^3.6.5", - "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", - "metro-runtime": "0.83.1" + "metro-runtime": "0.83.1", + "yaml": "^2.6.1" }, "devDependencies": { "@types/connect": "^3.4.35", diff --git a/packages/metro-config/src/__fixtures__/bad-root.metro.config.js b/packages/metro-config/src/__fixtures__/bad-root.metro.config.js new file mode 100644 index 0000000000..9ea8386201 --- /dev/null +++ b/packages/metro-config/src/__fixtures__/bad-root.metro.config.js @@ -0,0 +1,18 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +/*:: +import type {ConfigT, InputConfigT} from '../types'; +*/ + +module.exports = (defaultConfig /*: ConfigT */) /*:InputConfigT*/ => ({ + // $FlowExpectedError[incompatible-return] testing bad config + projectRoot: ['array'], +}); diff --git a/packages/metro-config/src/__fixtures__/bad-server.metro.config.js b/packages/metro-config/src/__fixtures__/bad-server.metro.config.js new file mode 100644 index 0000000000..e82e397344 --- /dev/null +++ b/packages/metro-config/src/__fixtures__/bad-server.metro.config.js @@ -0,0 +1,20 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +/*:: +import type {ConfigT, InputConfigT} from '../types'; +*/ + +module.exports = (defaultConfig /*: ConfigT */) /*:InputConfigT*/ => ({ + server: { + // $FlowExpectedError[incompatible-return] testing bad config + useGlobalHotkey: 'test', + }, +}); diff --git a/packages/metro-config/src/__fixtures__/basic.config.js b/packages/metro-config/src/__fixtures__/basic.config.js new file mode 100644 index 0000000000..82481901dc --- /dev/null +++ b/packages/metro-config/src/__fixtures__/basic.config.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +module.exports = { + // Use cacheVersion as a dummy free text field to check we've read the config + cacheVersion: 'basic-config', +}; diff --git a/packages/metro-config/src/__fixtures__/cachestores.config.js b/packages/metro-config/src/__fixtures__/cachestores.config.js new file mode 100644 index 0000000000..413601b00b --- /dev/null +++ b/packages/metro-config/src/__fixtures__/cachestores.config.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +/*:: +import type {InputConfigT} from '../types'; +*/ + +module.exports = { + cacheStores: ({FileStore}) => { + return [new FileStore({root: __dirname})]; + }, +} /*:: as InputConfigT*/; diff --git a/packages/metro-config/src/__fixtures__/cjs-sync-function.metro.config.js b/packages/metro-config/src/__fixtures__/cjs-sync-function.metro.config.js new file mode 100644 index 0000000000..6353f25f00 --- /dev/null +++ b/packages/metro-config/src/__fixtures__/cjs-sync-function.metro.config.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +/*:: +import type {ConfigT, InputConfigT} from '../types'; +*/ + +module.exports = (defaultConfig /*: ConfigT */) /*:InputConfigT*/ => ({ + cacheStores: [], + reporter: undefined, + maxWorkers: 2, + resolver: { + sourceExts: [...defaultConfig.resolver.sourceExts, 'tsx'], + hasteImplModulePath: 'test', + }, + transformerPath: '', +}); diff --git a/packages/metro-config/src/__fixtures__/custom-path.metro.config.js b/packages/metro-config/src/__fixtures__/custom-path.metro.config.js new file mode 100644 index 0000000000..fac7823446 --- /dev/null +++ b/packages/metro-config/src/__fixtures__/custom-path.metro.config.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +module.exports = { + // Use cacheVersion as a dummy free text field to check we've read the config + cacheVersion: 'custom-path', +}; diff --git a/packages/metro-config/src/__fixtures__/metro.config.js b/packages/metro-config/src/__fixtures__/metro.config.js new file mode 100644 index 0000000000..428809d428 --- /dev/null +++ b/packages/metro-config/src/__fixtures__/metro.config.js @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +module.exports = { + // Use cacheVersion as a dummy free text field to check we've read the config + cacheVersion: 'default-config', +}; diff --git a/packages/metro-config/src/__fixtures__/yaml-extensionless b/packages/metro-config/src/__fixtures__/yaml-extensionless new file mode 100644 index 0000000000..130a47fd1a --- /dev/null +++ b/packages/metro-config/src/__fixtures__/yaml-extensionless @@ -0,0 +1,2 @@ +# Use cacheVersion as a dummy free text field to check we've read the config +cacheVersion: yaml-extensionless diff --git a/packages/metro-config/src/__mocks__/cosmiconfig.js b/packages/metro-config/src/__mocks__/cosmiconfig.js deleted file mode 100644 index 5b0ac955ea..0000000000 --- a/packages/metro-config/src/__mocks__/cosmiconfig.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - * @oncall react_native - */ - -'use strict'; - -let resolvedConfig = {}; -let loadHasBeenCalled = false; -let returnNull = false; - -const cosmiconfig = jest.fn(() => ({ - search: async () => - returnNull - ? null - : { - filepath: '/metro.config.js', - config: resolvedConfig, - }, - load: async path => { - loadHasBeenCalled = true; - return { - filepath: path, - config: resolvedConfig, - }; - }, -})); - -cosmiconfig.setResolvedConfig = config => { - resolvedConfig = config; -}; - -cosmiconfig.setReturnNull = shouldReturnNull => { - returnNull = shouldReturnNull; -}; - -cosmiconfig.reset = () => { - loadHasBeenCalled = false; - returnNull = false; -}; - -cosmiconfig.hasLoadBeenCalled = () => { - return loadHasBeenCalled; -}; - -module.exports = cosmiconfig; diff --git a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap index 3552af2047..b93865ae53 100644 --- a/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap +++ b/packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap @@ -1,741 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`loadConfig can load config objects 1`] = ` -Object { - "cacheStores": Array [], - "cacheVersion": "1.0", - "maxWorkers": 2, - "projectRoot": "/", - "reporter": null, - "resetCache": false, - "resolver": Object { - "assetExts": Array [ - "bmp", - "gif", - "jpg", - "jpeg", - "png", - "psd", - "svg", - "webp", - "xml", - "m4v", - "mov", - "mp4", - "mpeg", - "mpg", - "webm", - "aac", - "aiff", - "caf", - "m4a", - "mp3", - "wav", - "html", - "pdf", - "yaml", - "yml", - "otf", - "ttf", - "zip", - ], - "assetResolutions": Array [ - "1", - "1.5", - "2", - "3", - "4", - ], - "blockList": /\\(\\\\/__tests__\\\\/\\.\\*\\)\\$/, - "dependencyExtractor": undefined, - "disableHierarchicalLookup": false, - "emptyModulePath": "metro-runtime/src/modules/empty-module", - "enableGlobalPackages": false, - "extraNodeModules": Object {}, - "hasteImplModulePath": undefined, - "nodeModulesPaths": Array [], - "platforms": Array [ - "ios", - "android", - "windows", - "web", - ], - "requireCycleIgnorePatterns": Array [ - /\\(\\^\\|\\\\/\\|\\\\\\\\\\)node_modules\\(\\$\\|\\\\/\\|\\\\\\\\\\)/, - ], - "resolveRequest": null, - "resolverMainFields": Array [ - "browser", - "main", - ], - "sourceExts": Array [ - "js", - "jsx", - "json", - "ts", - "tsx", - ], - "unstable_conditionNames": Array [], - "unstable_conditionsByPlatform": Object { - "web": Array [ - "browser", - ], - }, - "unstable_enablePackageExports": true, - "useWatchman": true, - }, - "serializer": Object { - "createModuleIdFactory": [Function], - "customSerializer": null, - "experimentalSerializerHook": [Function], - "getModulesRunBeforeMainModule": [Function], - "getPolyfills": [Function], - "getRunModuleStatement": [Function], - "isThirdPartyModule": [Function], - "polyfillModuleNames": Array [], - "processModuleFilter": [Function], - }, - "server": Object { - "enhanceMiddleware": [Function], - "forwardClientLogs": true, - "port": 8081, - "rewriteRequestUrl": [Function], - "unstable_serverRoot": null, - "useGlobalHotkey": true, - "verifyConnections": false, - }, - "stickyWorkers": true, - "symbolicator": Object { - "customizeFrame": [Function], - "customizeStack": [Function], - }, - "transformer": Object { - "allowOptionalDependencies": false, - "assetPlugins": Array [], - "assetRegistryPath": "missing-asset-registry-path", - "asyncRequireModulePath": "metro-runtime/src/modules/asyncRequire", - "babelTransformerPath": "metro-babel-transformer", - "dynamicDepsInPackages": "throwAtRuntime", - "enableBabelRCLookup": true, - "enableBabelRuntime": true, - "getTransformOptions": [Function], - "globalPrefix": "", - "hermesParser": false, - "minifierConfig": Object { - "compress": Object { - "reduce_funcs": false, - }, - "mangle": Object { - "toplevel": false, - }, - "output": Object { - "ascii_only": true, - "quote_style": 3, - "wrap_iife": true, - }, - "sourceMap": Object { - "includeSources": false, - }, - "toplevel": false, - }, - "minifierPath": "metro-minify-terser", - "optimizationSizeLimit": 153600, - "publicPath": "/assets", - "transformVariants": Object { - "default": Object {}, - }, - "unstable_allowRequireContext": false, - "unstable_compactOutput": false, - "unstable_dependencyMapReservedName": null, - "unstable_disableModuleWrapping": false, - "unstable_disableNormalizePseudoGlobals": false, - "unstable_memoizeInlineRequires": false, - "unstable_renameRequire": true, - "unstable_workerThreads": false, - }, - "transformerPath": "", - "unstable_perfLoggerFactory": [Function], - "watchFolders": Array [ - "/", - ], - "watcher": Object { - "additionalExts": Array [ - "cjs", - "mjs", - ], - "healthCheck": Object { - "enabled": false, - "filePrefix": ".metro-health-check", - "interval": 30000, - "timeout": 5000, - }, - "unstable_autoSaveCache": Object { - "debounceMs": 5000, - "enabled": true, - }, - "unstable_lazySha1": true, - "unstable_workerThreads": false, - "watchman": Object { - "deferStates": Array [ - "hg.update", - ], - }, - }, -} -`; - -exports[`loadConfig can load the config from a path 1`] = ` -Object { - "cacheStores": Array [], - "cacheVersion": "1.0", - "maxWorkers": 2, - "projectRoot": "/", - "reporter": null, - "resetCache": false, - "resolver": Object { - "assetExts": Array [ - "bmp", - "gif", - "jpg", - "jpeg", - "png", - "psd", - "svg", - "webp", - "xml", - "m4v", - "mov", - "mp4", - "mpeg", - "mpg", - "webm", - "aac", - "aiff", - "caf", - "m4a", - "mp3", - "wav", - "html", - "pdf", - "yaml", - "yml", - "otf", - "ttf", - "zip", - ], - "assetResolutions": Array [ - "1", - "1.5", - "2", - "3", - "4", - ], - "blockList": /\\(\\\\/__tests__\\\\/\\.\\*\\)\\$/, - "dependencyExtractor": undefined, - "disableHierarchicalLookup": false, - "emptyModulePath": "metro-runtime/src/modules/empty-module", - "enableGlobalPackages": false, - "extraNodeModules": Object {}, - "hasteImplModulePath": undefined, - "nodeModulesPaths": Array [], - "platforms": Array [ - "ios", - "android", - "windows", - "web", - ], - "requireCycleIgnorePatterns": Array [ - /\\(\\^\\|\\\\/\\|\\\\\\\\\\)node_modules\\(\\$\\|\\\\/\\|\\\\\\\\\\)/, - ], - "resolveRequest": null, - "resolverMainFields": Array [ - "browser", - "main", - ], - "sourceExts": Array [ - "js", - "jsx", - "json", - "ts", - "tsx", - ], - "unstable_conditionNames": Array [], - "unstable_conditionsByPlatform": Object { - "web": Array [ - "browser", - ], - }, - "unstable_enablePackageExports": true, - "useWatchman": true, - }, - "serializer": Object { - "createModuleIdFactory": [Function], - "customSerializer": null, - "experimentalSerializerHook": [Function], - "getModulesRunBeforeMainModule": [Function], - "getPolyfills": [Function], - "getRunModuleStatement": [Function], - "isThirdPartyModule": [Function], - "polyfillModuleNames": Array [], - "processModuleFilter": [Function], - }, - "server": Object { - "enhanceMiddleware": [Function], - "forwardClientLogs": true, - "port": 8081, - "rewriteRequestUrl": [Function], - "unstable_serverRoot": null, - "useGlobalHotkey": true, - "verifyConnections": false, - }, - "stickyWorkers": true, - "symbolicator": Object { - "customizeFrame": [Function], - "customizeStack": [Function], - }, - "transformer": Object { - "allowOptionalDependencies": false, - "assetPlugins": Array [], - "assetRegistryPath": "missing-asset-registry-path", - "asyncRequireModulePath": "metro-runtime/src/modules/asyncRequire", - "babelTransformerPath": "metro-babel-transformer/src/index.js", - "dynamicDepsInPackages": "throwAtRuntime", - "enableBabelRCLookup": true, - "enableBabelRuntime": true, - "getTransformOptions": [Function], - "globalPrefix": "", - "hermesParser": false, - "minifierConfig": Object { - "compress": Object { - "reduce_funcs": false, - }, - "mangle": Object { - "toplevel": false, - }, - "output": Object { - "ascii_only": true, - "quote_style": 3, - "wrap_iife": true, - }, - "sourceMap": Object { - "includeSources": false, - }, - "toplevel": false, - }, - "minifierPath": "metro-minify-terser", - "optimizationSizeLimit": 153600, - "publicPath": "/assets", - "transformVariants": Object { - "default": Object {}, - }, - "unstable_allowRequireContext": false, - "unstable_compactOutput": false, - "unstable_dependencyMapReservedName": null, - "unstable_disableModuleWrapping": false, - "unstable_disableNormalizePseudoGlobals": false, - "unstable_memoizeInlineRequires": false, - "unstable_renameRequire": true, - "unstable_workerThreads": false, - }, - "transformerPath": "", - "unstable_perfLoggerFactory": [Function], - "watchFolders": Array [ - "/", - ], - "watcher": Object { - "additionalExts": Array [ - "cjs", - "mjs", - ], - "healthCheck": Object { - "enabled": false, - "filePrefix": ".metro-health-check", - "interval": 30000, - "timeout": 5000, - }, - "unstable_autoSaveCache": Object { - "debounceMs": 5000, - "enabled": true, - }, - "unstable_lazySha1": true, - "unstable_workerThreads": false, - "watchman": Object { - "deferStates": Array [ - "hg.update", - ], - }, - }, -} -`; - -exports[`loadConfig can load the config from a path pointing to a directory 1`] = ` -Object { - "cacheStores": Array [], - "cacheVersion": "1.0", - "maxWorkers": 2, - "projectRoot": "/", - "reporter": null, - "resetCache": false, - "resolver": Object { - "assetExts": Array [ - "bmp", - "gif", - "jpg", - "jpeg", - "png", - "psd", - "svg", - "webp", - "xml", - "m4v", - "mov", - "mp4", - "mpeg", - "mpg", - "webm", - "aac", - "aiff", - "caf", - "m4a", - "mp3", - "wav", - "html", - "pdf", - "yaml", - "yml", - "otf", - "ttf", - "zip", - ], - "assetResolutions": Array [ - "1", - "1.5", - "2", - "3", - "4", - ], - "blockList": /\\(\\\\/__tests__\\\\/\\.\\*\\)\\$/, - "dependencyExtractor": undefined, - "disableHierarchicalLookup": false, - "emptyModulePath": "metro-runtime/src/modules/empty-module", - "enableGlobalPackages": false, - "extraNodeModules": Object {}, - "hasteImplModulePath": undefined, - "nodeModulesPaths": Array [], - "platforms": Array [ - "ios", - "android", - "windows", - "web", - ], - "requireCycleIgnorePatterns": Array [ - /\\(\\^\\|\\\\/\\|\\\\\\\\\\)node_modules\\(\\$\\|\\\\/\\|\\\\\\\\\\)/, - ], - "resolveRequest": null, - "resolverMainFields": Array [ - "browser", - "main", - ], - "sourceExts": Array [ - "js", - "jsx", - "json", - "ts", - "tsx", - ], - "unstable_conditionNames": Array [], - "unstable_conditionsByPlatform": Object { - "web": Array [ - "browser", - ], - }, - "unstable_enablePackageExports": true, - "useWatchman": true, - }, - "serializer": Object { - "createModuleIdFactory": [Function], - "customSerializer": null, - "experimentalSerializerHook": [Function], - "getModulesRunBeforeMainModule": [Function], - "getPolyfills": [Function], - "getRunModuleStatement": [Function], - "isThirdPartyModule": [Function], - "polyfillModuleNames": Array [], - "processModuleFilter": [Function], - }, - "server": Object { - "enhanceMiddleware": [Function], - "forwardClientLogs": true, - "port": 8081, - "rewriteRequestUrl": [Function], - "unstable_serverRoot": null, - "useGlobalHotkey": true, - "verifyConnections": false, - }, - "stickyWorkers": true, - "symbolicator": Object { - "customizeFrame": [Function], - "customizeStack": [Function], - }, - "transformer": Object { - "allowOptionalDependencies": false, - "assetPlugins": Array [], - "assetRegistryPath": "missing-asset-registry-path", - "asyncRequireModulePath": "metro-runtime/src/modules/asyncRequire", - "babelTransformerPath": "metro-babel-transformer/src/index.js", - "dynamicDepsInPackages": "throwAtRuntime", - "enableBabelRCLookup": true, - "enableBabelRuntime": true, - "getTransformOptions": [Function], - "globalPrefix": "", - "hermesParser": false, - "minifierConfig": Object { - "compress": Object { - "reduce_funcs": false, - }, - "mangle": Object { - "toplevel": false, - }, - "output": Object { - "ascii_only": true, - "quote_style": 3, - "wrap_iife": true, - }, - "sourceMap": Object { - "includeSources": false, - }, - "toplevel": false, - }, - "minifierPath": "metro-minify-terser", - "optimizationSizeLimit": 153600, - "publicPath": "/assets", - "transformVariants": Object { - "default": Object {}, - }, - "unstable_allowRequireContext": false, - "unstable_compactOutput": false, - "unstable_dependencyMapReservedName": null, - "unstable_disableModuleWrapping": false, - "unstable_disableNormalizePseudoGlobals": false, - "unstable_memoizeInlineRequires": false, - "unstable_renameRequire": true, - "unstable_workerThreads": false, - }, - "transformerPath": "", - "unstable_perfLoggerFactory": [Function], - "watchFolders": Array [ - "/", - ], - "watcher": Object { - "additionalExts": Array [ - "cjs", - "mjs", - ], - "healthCheck": Object { - "enabled": false, - "filePrefix": ".metro-health-check", - "interval": 30000, - "timeout": 5000, - }, - "unstable_autoSaveCache": Object { - "debounceMs": 5000, - "enabled": true, - }, - "unstable_lazySha1": true, - "unstable_workerThreads": false, - "watchman": Object { - "deferStates": Array [ - "hg.update", - ], - }, - }, -} -`; - -exports[`loadConfig injects \`metro-cache\` into the \`cacheStores\` callback 1`] = ` -Object { - "cacheStores": Array [], - "cacheVersion": "1.0", - "maxWorkers": 2, - "projectRoot": "/", - "reporter": null, - "resetCache": false, - "resolver": Object { - "assetExts": Array [ - "bmp", - "gif", - "jpg", - "jpeg", - "png", - "psd", - "svg", - "webp", - "xml", - "m4v", - "mov", - "mp4", - "mpeg", - "mpg", - "webm", - "aac", - "aiff", - "caf", - "m4a", - "mp3", - "wav", - "html", - "pdf", - "yaml", - "yml", - "otf", - "ttf", - "zip", - ], - "assetResolutions": Array [ - "1", - "1.5", - "2", - "3", - "4", - ], - "blockList": /\\(\\\\/__tests__\\\\/\\.\\*\\)\\$/, - "dependencyExtractor": undefined, - "disableHierarchicalLookup": false, - "emptyModulePath": "metro-runtime/src/modules/empty-module", - "enableGlobalPackages": false, - "extraNodeModules": Object {}, - "hasteImplModulePath": undefined, - "nodeModulesPaths": Array [], - "platforms": Array [ - "ios", - "android", - "windows", - "web", - ], - "requireCycleIgnorePatterns": Array [ - /\\(\\^\\|\\\\/\\|\\\\\\\\\\)node_modules\\(\\$\\|\\\\/\\|\\\\\\\\\\)/, - ], - "resolveRequest": null, - "resolverMainFields": Array [ - "browser", - "main", - ], - "sourceExts": Array [ - "js", - "jsx", - "json", - "ts", - "tsx", - ], - "unstable_conditionNames": Array [], - "unstable_conditionsByPlatform": Object { - "web": Array [ - "browser", - ], - }, - "unstable_enablePackageExports": true, - "useWatchman": true, - }, - "serializer": Object { - "createModuleIdFactory": [Function], - "customSerializer": null, - "experimentalSerializerHook": [Function], - "getModulesRunBeforeMainModule": [Function], - "getPolyfills": [Function], - "getRunModuleStatement": [Function], - "isThirdPartyModule": [Function], - "polyfillModuleNames": Array [], - "processModuleFilter": [Function], - }, - "server": Object { - "enhanceMiddleware": [Function], - "forwardClientLogs": true, - "port": 8081, - "rewriteRequestUrl": [Function], - "unstable_serverRoot": null, - "useGlobalHotkey": true, - "verifyConnections": false, - }, - "stickyWorkers": true, - "symbolicator": Object { - "customizeFrame": [Function], - "customizeStack": [Function], - }, - "transformer": Object { - "allowOptionalDependencies": false, - "assetPlugins": Array [], - "assetRegistryPath": "missing-asset-registry-path", - "asyncRequireModulePath": "metro-runtime/src/modules/asyncRequire", - "babelTransformerPath": "metro-babel-transformer", - "dynamicDepsInPackages": "throwAtRuntime", - "enableBabelRCLookup": true, - "enableBabelRuntime": true, - "getTransformOptions": [Function], - "globalPrefix": "", - "hermesParser": false, - "minifierConfig": Object { - "compress": Object { - "reduce_funcs": false, - }, - "mangle": Object { - "toplevel": false, - }, - "output": Object { - "ascii_only": true, - "quote_style": 3, - "wrap_iife": true, - }, - "sourceMap": Object { - "includeSources": false, - }, - "toplevel": false, - }, - "minifierPath": "metro-minify-terser", - "optimizationSizeLimit": 153600, - "publicPath": "/assets", - "transformVariants": Object { - "default": Object {}, - }, - "unstable_allowRequireContext": false, - "unstable_compactOutput": false, - "unstable_dependencyMapReservedName": null, - "unstable_disableModuleWrapping": false, - "unstable_disableNormalizePseudoGlobals": false, - "unstable_memoizeInlineRequires": false, - "unstable_renameRequire": true, - "unstable_workerThreads": false, - }, - "transformerPath": "", - "unstable_perfLoggerFactory": [Function], - "watchFolders": Array [ - "/", - ], - "watcher": Object { - "additionalExts": Array [ - "cjs", - "mjs", - ], - "healthCheck": Object { - "enabled": false, - "filePrefix": ".metro-health-check", - "interval": 30000, - "timeout": 5000, - }, - "unstable_autoSaveCache": Object { - "debounceMs": 5000, - "enabled": true, - }, - "unstable_lazySha1": true, - "unstable_workerThreads": false, - "watchman": Object { - "deferStates": Array [ - "hg.update", - ], - }, - }, -} -`; - exports[`loadConfig validates config for projectRoot 1`] = ` "● Validation Error: diff --git a/packages/metro-config/src/__tests__/loadConfig-test.js b/packages/metro-config/src/__tests__/loadConfig-test.js index f039f3982f..49377d88d5 100644 --- a/packages/metro-config/src/__tests__/loadConfig-test.js +++ b/packages/metro-config/src/__tests__/loadConfig-test.js @@ -12,60 +12,52 @@ // eslint-disable-next-line lint/sort-imports import getDefaultConfig from '../defaults'; -jest.mock('cosmiconfig'); - const {loadConfig} = require('../loadConfig'); -const cosmiconfig = require('cosmiconfig'); const path = require('path'); const prettyFormat = require('pretty-format'); const util = require('util'); +const FIXTURES = path.resolve(__dirname, '../__fixtures__'); + describe('loadConfig', () => { beforeEach(() => { - cosmiconfig.reset(); + jest.spyOn(console, 'warn').mockImplementation(() => {}); + jest.clearAllMocks(); }); - test('can load config objects', async () => { - const config: any = { - reporter: null, - maxWorkers: 2, - cacheStores: [], - transformerPath: '', - resolver: { - emptyModulePath: 'metro-runtime/src/modules/empty-module', - }, - }; - - cosmiconfig.setResolvedConfig(config); - - const result = await loadConfig({}); - - expect(result).toMatchSnapshot(); - expect(result.cacheStores).toEqual([]); + test('can load the config from a path', async () => { + // We don't actually use the specified file in this test but it needs to + // resolve to a real file on the file system. + const result = await loadConfig({ + config: path.resolve(FIXTURES, 'custom-path.metro.config.js'), + }); + expect(result).toMatchObject({ + cacheVersion: 'custom-path', + }); }); - test('can load config from function', async () => { - const config = (defaultConfig: any): any => ({ - ...defaultConfig, - cacheStores: [], - reporter: null, - maxWorkers: 2, - resolver: { - sourceExts: [...defaultConfig.resolver.sourceExts, 'tsx'], - hasteImplModulePath: 'test', - }, - transformerPath: '', + test('can load config objects', async () => { + const result = await loadConfig({ + config: path.resolve(FIXTURES, 'basic.config.js'), }); + expect(result.cacheVersion).toEqual('basic-config'); + }); - cosmiconfig.setResolvedConfig(config); - + test('can load config from function', async () => { const defaultConfigOverrides = { resolver: { sourceExts: ['json', 're'], }, }; - - const result = await loadConfig({}, defaultConfigOverrides); + const result = await loadConfig( + { + config: path.resolve( + __dirname, + '../__fixtures__/cjs-sync-function.metro.config.js', + ), + }, + defaultConfigOverrides, + ); const defaults = await getDefaultConfig(); expect(result.resolver).toMatchObject({ assetExts: defaults.resolver.assetExts, @@ -74,88 +66,21 @@ describe('loadConfig', () => { }); }); - test('can load the config from a path', async () => { - const config = (defaultConfig: any): any => ({ - ...defaultConfig, - projectRoot: '/', - reporter: null, - maxWorkers: 2, - cacheStores: [], - transformerPath: '', - resolver: { - emptyModulePath: 'metro-runtime/src/modules/empty-module', - }, - }); - - cosmiconfig.setResolvedConfig(config); - - // We don't actually use the specified file in this test but it needs to - // resolve to a real file on the file system. - const result = await loadConfig({config: './__tests__/loadConfig-test.js'}); - - const relativizedResult = { - ...result, - transformer: { - // Remove absolute paths from the result. - ...result.transformer, - babelTransformerPath: path.relative( - path.join( - require.resolve('metro-babel-transformer'), - '..', - '..', - '..', - ), - result.transformer.babelTransformerPath, - ), - }, - }; - expect(relativizedResult).toMatchSnapshot(); - expect(cosmiconfig.hasLoadBeenCalled()).toBeTruthy(); - }); - test('can load the config from a path pointing to a directory', async () => { - const config = (defaultConfig: any): any => ({ - ...defaultConfig, - projectRoot: '/', - reporter: null, - maxWorkers: 2, - cacheStores: [], - transformerPath: '', - resolver: { - emptyModulePath: 'metro-runtime/src/modules/empty-module', - }, - }); - - cosmiconfig.setResolvedConfig(config); - // We don't actually use the specified file in this test but it needs to // resolve to a real file on the file system. - const result = await loadConfig({config: path.resolve(__dirname, '../')}); - - const relativizedResult = { - ...result, - transformer: { - ...result.transformer, - // Remove absolute paths from the result. - babelTransformerPath: path.relative( - path.join( - require.resolve('metro-babel-transformer'), - '..', - '..', - '..', - ), - result.transformer.babelTransformerPath, - ), - }, - }; - expect(relativizedResult).toMatchSnapshot(); - expect(cosmiconfig.hasLoadBeenCalled()).toBeTruthy(); + const result = await loadConfig({cwd: FIXTURES}); + expect(result).toMatchObject({ + cacheVersion: 'default-config', + }); }); test('can load the config with no config present', async () => { - cosmiconfig.setReturnNull(true); - + jest.mock('fs', () => ({ + existsSync: jest.fn(() => false), + })); const result = await loadConfig({cwd: process.cwd()}); + jest.unmock('fs'); let defaultConfig = await getDefaultConfig(process.cwd()); defaultConfig = { @@ -170,17 +95,10 @@ describe('loadConfig', () => { test('validates config for server', async () => { expect.assertions(1); - const config = (defaultConfig: any) => ({ - ...defaultConfig, - server: { - useGlobalHotkey: 'test', - }, - }); - - cosmiconfig.setResolvedConfig(config); - try { - await loadConfig({}); + await loadConfig({ + config: path.resolve(FIXTURES, 'bad-server.metro.config.js'), + }); } catch (error) { expect(util.stripVTControlCharacters(error.message)).toMatchSnapshot(); } @@ -188,37 +106,31 @@ describe('loadConfig', () => { test('validates config for projectRoot', async () => { expect.assertions(1); - const config = (defaultConfig: any) => ({ - ...defaultConfig, - projectRoot: ['test'], - }); - - cosmiconfig.setResolvedConfig(config); - try { - await loadConfig({}); + await loadConfig({ + config: path.resolve(FIXTURES, 'bad-root.metro.config.js'), + }); } catch (error) { expect(util.stripVTControlCharacters(error.message)).toMatchSnapshot(); } }); test('injects `metro-cache` into the `cacheStores` callback', async () => { - const config = { - reporter: null, - maxWorkers: 2, - cacheStores: jest.fn(() => []), - transformerPath: '', - resolver: { - emptyModulePath: 'metro-runtime/src/modules/empty-module', - }, - }; - - cosmiconfig.setResolvedConfig(config); - - const result = await loadConfig({}); + const result = await loadConfig({ + config: path.resolve(FIXTURES, 'cachestores.config.js'), + }); + expect(result.cacheStores[0]).toBeInstanceOf( + require('metro-cache').FileStore, + ); + }); - expect(result).toMatchSnapshot(); - expect(result.cacheStores).toEqual([]); - expect(config.cacheStores).toBeCalledWith(require('metro-cache')); + test('supports loading YAML (deprecated)', async () => { + const result = await loadConfig({ + config: path.resolve(FIXTURES, 'yaml-extensionless'), + }); + expect(console.warn).toHaveBeenCalledWith( + 'YAML config is deprecated, please migrate to JavaScript config (e.g. metro.config.js)', + ); + expect(result.cacheVersion).toEqual('yaml-extensionless'); }); }); diff --git a/packages/metro-config/src/loadConfig.js b/packages/metro-config/src/loadConfig.js index f5ed2cff8b..421fb44810 100644 --- a/packages/metro-config/src/loadConfig.js +++ b/packages/metro-config/src/loadConfig.js @@ -13,14 +13,15 @@ import type {ConfigT, InputConfigT, YargArguments} from './types'; import getDefaultConfig from './defaults'; import validConfig from './defaults/validConfig'; -import cosmiconfig from 'cosmiconfig'; import fs from 'fs'; import {validate} from 'jest-validate'; import * as MetroCache from 'metro-cache'; +import {homedir} from 'os'; import path from 'path'; import {dirname, join} from 'path'; +import {parse as parseYaml} from 'yaml'; -type CosmiConfigResult = { +type ResolveConfigResult = { filepath: string, isEmpty: boolean, config: (ConfigT => Promise) | (ConfigT => ConfigT) | InputConfigT, @@ -43,23 +44,18 @@ function overrideArgument(arg: Array | T): T { return arg; } -const explorer = cosmiconfig('metro', { - searchPlaces: [ - 'metro.config.js', - 'metro.config.cjs', - 'metro.config.json', - 'package.json', - ], - loaders: { - '.json': cosmiconfig.loadJson, - '.yaml': cosmiconfig.loadYaml, - '.yml': cosmiconfig.loadYaml, - '.js': cosmiconfig.loadJs, - '.cjs': cosmiconfig.loadJs, - '.es6': cosmiconfig.loadJs, - noExt: cosmiconfig.loadYaml, - }, -}); +const SEARCH_PLACES = [ + 'metro.config.js', + 'metro.config.cjs', + 'metro.config.json', + 'package.json', +]; + +const JS_EXTENSIONS = new Set(['.json', '.js', '.cjs', '.es6']); +const YAML_EXTENSIONS = new Set(['.yml', '.yaml', '']); + +const PACKAGE_JSON = path.sep + 'package.json'; +const PACKAGE_JSON_PROP_NAME = 'metro'; const isFile = (filePath: string) => fs.existsSync(filePath) && !fs.lstatSync(filePath).isDirectory(); @@ -82,13 +78,13 @@ const resolve = (filePath: string) => { async function resolveConfig( filePath?: string, cwd?: string, -): Promise { - if (filePath) { - return explorer.load(resolve(filePath)); - } +): Promise { + const configPath: ?string = + filePath != null + ? resolve(filePath) + : searchForConfigFile(path.resolve(process.cwd(), cwd ?? ''), homedir()); - const result = await explorer.search(cwd); - if (result == null) { + if (configPath == null) { // No config file found, return a default return { isEmpty: true, @@ -96,8 +92,7 @@ async function resolveConfig( config: {}, }; } - - return result; + return await loadConfigFile(configPath); } function mergeConfig>( @@ -190,7 +185,7 @@ async function loadMetroConfigFromDisk( cwd?: string, defaultConfigOverrides: InputConfigT, ): Promise { - const resolvedConfigResults: CosmiConfigResult = await resolveConfig( + const resolvedConfigResults: ResolveConfigResult = await resolveConfig( path, cwd, ); @@ -319,4 +314,71 @@ async function loadConfig( }); } +export async function loadConfigFile( + absolutePath: string, +): Promise { + let config; + const extension = path.extname(absolutePath); + + if (JS_EXTENSIONS.has(extension)) { + // $FlowIgnore[unsupported-syntax] + const configModule = require(absolutePath); + if (absolutePath.endsWith(PACKAGE_JSON)) { + config = configModule[PACKAGE_JSON_PROP_NAME]; + } else { + config = configModule.__esModule ? configModule.default : configModule; + } + } else if (YAML_EXTENSIONS.has(extension)) { + console.warn( + 'YAML config is deprecated, please migrate to JavaScript config (e.g. metro.config.js)', + ); + config = parseYaml(fs.readFileSync(absolutePath, 'utf8')); + } else { + throw new Error( + `Unsupported config file extension: ${extension}. ` + + `Supported extensions are ${[...JS_EXTENSIONS, ...YAML_EXTENSIONS].map(ext => (ext === '' ? 'none' : `${ext}`)).join()})}.`, + ); + } + + return { + isEmpty: false, + filepath: absolutePath, + config, + }; +} + +export function searchForConfigFile( + absoluteStartDir: string, + absoluteStopDir: string, +): ?string { + for ( + let currentDir: string = absoluteStartDir, prevDir: string; + prevDir !== currentDir && prevDir !== absoluteStopDir; + currentDir = path.dirname(prevDir) + ) { + for (const candidate of SEARCH_PLACES) { + const candidatePath = path.join(currentDir, candidate); + if (isFile(candidatePath)) { + if (candidatePath.endsWith(path.sep + 'package.json')) { + // package.json is a special case - we only find a config if + // the json has a top-level `metro` key. + // + // By using `require`, we'll add the json to the Node.js module + // cache, so we don't incur further parse cost after returning the + // manifest's path. + // $FlowIgnore[unsupported-syntax] dynamic require + const content = require(candidatePath); + if (Object.hasOwn(content, PACKAGE_JSON_PROP_NAME)) { + return candidatePath; + } + } else { + return candidatePath; + } + } + } + prevDir = currentDir; + } + return null; +} + export {loadConfig, resolveConfig, mergeConfig}; diff --git a/packages/metro/src/integration_tests/__tests__/build-errors-test.js b/packages/metro/src/integration_tests/__tests__/build-errors-test.js index fd6e36c9f8..a94a3326d4 100644 --- a/packages/metro/src/integration_tests/__tests__/build-errors-test.js +++ b/packages/metro/src/integration_tests/__tests__/build-errors-test.js @@ -14,7 +14,6 @@ const Metro = require('../../..'); const path = require('path'); -jest.unmock('cosmiconfig'); jest.setTimeout(30 * 1000); const BUILD_ERRORS_SRC_DIR = path.resolve(__dirname, '..', 'basic_bundle', 'build-errors') + path.sep; diff --git a/packages/metro/src/integration_tests/__tests__/build-test.js b/packages/metro/src/integration_tests/__tests__/build-test.js index 3eb8344bcc..218b424988 100644 --- a/packages/metro/src/integration_tests/__tests__/build-test.js +++ b/packages/metro/src/integration_tests/__tests__/build-test.js @@ -16,8 +16,6 @@ const execBundle = require('../execBundle'); const MetroConfig = require('metro-config'); const path = require('path'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); const INPUT_PATH = path.resolve(__dirname, '../basic_bundle'); diff --git a/packages/metro/src/integration_tests/__tests__/buildGraph-test.js b/packages/metro/src/integration_tests/__tests__/buildGraph-test.js index 10894fbd3d..27559711b4 100644 --- a/packages/metro/src/integration_tests/__tests__/buildGraph-test.js +++ b/packages/metro/src/integration_tests/__tests__/buildGraph-test.js @@ -15,7 +15,6 @@ import CountingSet from '../../lib/CountingSet'; const Metro = require('../../..'); const path = require('path'); -jest.unmock('cosmiconfig'); jest.useRealTimers(); jest.setTimeout(120 * 1000); diff --git a/packages/metro/src/integration_tests/__tests__/import-export-test.js b/packages/metro/src/integration_tests/__tests__/import-export-test.js index 6261d124c4..e384dba72f 100644 --- a/packages/metro/src/integration_tests/__tests__/import-export-test.js +++ b/packages/metro/src/integration_tests/__tests__/import-export-test.js @@ -13,8 +13,6 @@ const Metro = require('../../..'); const execBundle = require('../execBundle'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); test('builds a simple bundle', async () => { diff --git a/packages/metro/src/integration_tests/__tests__/optional-dependencies-test.js b/packages/metro/src/integration_tests/__tests__/optional-dependencies-test.js index 2e7f61e90f..68d016b0ba 100644 --- a/packages/metro/src/integration_tests/__tests__/optional-dependencies-test.js +++ b/packages/metro/src/integration_tests/__tests__/optional-dependencies-test.js @@ -13,8 +13,6 @@ const Metro = require('../../..'); const execBundle = require('../execBundle'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); test('builds a simple bundle', async () => { diff --git a/packages/metro/src/integration_tests/__tests__/rambundle-test.js b/packages/metro/src/integration_tests/__tests__/rambundle-test.js index 6d15b98674..b18867d400 100644 --- a/packages/metro/src/integration_tests/__tests__/rambundle-test.js +++ b/packages/metro/src/integration_tests/__tests__/rambundle-test.js @@ -17,8 +17,6 @@ const os = require('os'); const path = require('path'); const vm = require('vm'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); test('builds and executes a RAM bundle', async () => { diff --git a/packages/metro/src/integration_tests/__tests__/require-context-test.js b/packages/metro/src/integration_tests/__tests__/require-context-test.js index 02cb888c23..82595d5ea3 100644 --- a/packages/metro/src/integration_tests/__tests__/require-context-test.js +++ b/packages/metro/src/integration_tests/__tests__/require-context-test.js @@ -13,8 +13,6 @@ const Metro = require('../../..'); const execBundle = require('../execBundle'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); test('require-context/matching.js', async () => { diff --git a/packages/metro/src/integration_tests/__tests__/require-resolveWeak-test.js b/packages/metro/src/integration_tests/__tests__/require-resolveWeak-test.js index 435351d1e5..f71b0ec2ac 100644 --- a/packages/metro/src/integration_tests/__tests__/require-resolveWeak-test.js +++ b/packages/metro/src/integration_tests/__tests__/require-resolveWeak-test.js @@ -13,8 +13,6 @@ const Metro = require('../../..'); const execBundle = require('../execBundle'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); test('resolveWeak() returns a different ID for each resolved module', async () => { diff --git a/packages/metro/src/integration_tests/__tests__/server-test.js b/packages/metro/src/integration_tests/__tests__/server-test.js index 384126d218..a4d7edab6a 100644 --- a/packages/metro/src/integration_tests/__tests__/server-test.js +++ b/packages/metro/src/integration_tests/__tests__/server-test.js @@ -15,7 +15,6 @@ const execBundle = require('../execBundle'); const fs = require('fs'); const path = require('path'); -jest.unmock('cosmiconfig'); jest.useRealTimers(); jest.setTimeout(60 * 1000); diff --git a/packages/metro/src/integration_tests/__tests__/server-torn-down-test.js b/packages/metro/src/integration_tests/__tests__/server-torn-down-test.js index 39a04a88a0..93fff1d2e5 100644 --- a/packages/metro/src/integration_tests/__tests__/server-torn-down-test.js +++ b/packages/metro/src/integration_tests/__tests__/server-torn-down-test.js @@ -13,8 +13,6 @@ const Metro = require('../../..'); // $FlowFixMe[cannot-resolve-module] - Untyped module const asyncHooks = require('async_hooks'); -jest.unmock('cosmiconfig'); - jest.useRealTimers(); jest.setTimeout(10000); diff --git a/packages/metro/src/integration_tests/__tests__/sourcemap-test.js b/packages/metro/src/integration_tests/__tests__/sourcemap-test.js index 7a83ed6fc0..f68a23dd6e 100644 --- a/packages/metro/src/integration_tests/__tests__/sourcemap-test.js +++ b/packages/metro/src/integration_tests/__tests__/sourcemap-test.js @@ -16,8 +16,6 @@ const fs = require('fs'); const sourceMap = require('source-map'); const stackTrace = require('stack-trace'); -jest.unmock('cosmiconfig'); - jest.setTimeout(30 * 1000); const INLINE_SOURCE_MAP_STR = diff --git a/yarn.lock b/yarn.lock index 47711b4028..f2196c0088 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1914,25 +1914,6 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2115,16 +2096,6 @@ core-js-pure@^3.30.2: resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.41.0.tgz#349fecad168d60807a31e83c99d73d786fe80811" integrity sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q== -cosmiconfig@^5.0.5: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - create-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" @@ -3110,14 +3081,6 @@ image-size@^1.0.2: dependencies: queue "6.0.2" -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" @@ -3217,11 +3180,6 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -4011,11 +3969,6 @@ jsesc@~3.0.2: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -4536,14 +4489,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -4843,11 +4788,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -5533,6 +5473,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.6.1.tgz#42f2b1ba89203f374609572d5349fb8686500773" + integrity sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg== + yargs-parser@^21.0.0, yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"