diff --git a/.yarnrc.yml b/.yarnrc.yml index c7f02e4b9..bd2e4a7ee 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -14,6 +14,9 @@ compressionLevel: 0 dynamicPackageExtensions: ./scripts/dependencies.config.js +dynamicPackageOverrides: + - id: nx + enableGlobalCache: false enableScripts: false @@ -72,6 +75,7 @@ plugins: - path: .yarn/plugins/@yarnpkg/plugin-compat.cjs spec: "@yarnpkg/plugin-compat" - path: incubator/yarn-plugin-dynamic-extensions/index.js + - path: incubator/yarn-plugin-dynamic-overrides/index.js - path: incubator/yarn-plugin-external-workspaces/dist/external-workspaces.cjs - path: incubator/yarn-plugin-ignore/dist/yarn-plugin-ignore.cjs - path: incubator/yarn-plugin-install-to/dist/yarn-plugin-install-to.cjs diff --git a/incubator/yarn-plugin-dynamic-overrides/README.md b/incubator/yarn-plugin-dynamic-overrides/README.md new file mode 100644 index 000000000..c40b35a93 --- /dev/null +++ b/incubator/yarn-plugin-dynamic-overrides/README.md @@ -0,0 +1,61 @@ +# @rnx-kit/yarn-plugin-dynamic-overrides + +[![Build](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml/badge.svg)](https://github.com/microsoft/rnx-kit/actions/workflows/build.yml) +[![npm version](https://img.shields.io/npm/v/@rnx-kit/yarn-plugin-dynamic-overrides)](https://www.npmjs.com/package/@rnx-kit/yarn-plugin-dynamic-overrides) + +🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 + +### THIS TOOL IS EXPERIMENTAL — USE WITH CAUTION + +🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧🚧 + +This is a Yarn plugin that lets you override a package's dependencies to allow +greater version ranges than the package declares. + +## Motivation + +A number of packages use explicit version numbers instead of version ranges, +forcing package managers to install multiple copies of a dependency even though +a more recent version is still compatible. + +This plugin attempts to address to by replacing the explicit version with a +version range. This is useful for deduping and allows for updating dependencies +to a more recent version. + +## Installation + +```sh +yarn plugin import https://raw.githubusercontent.com/microsoft/rnx-kit/main/incubator/yarn-plugin-dynamic-overrides/index.js +``` + +## Usage + +List the packages that you want to override in `.yarnrc.yml`. For example, to +override dependencies of `@appium/base-driver`: + +```yml +dynamicPackageOverrides: + - id: "@appium/base-driver" +``` + +Next time you run `yarn install`, its dependencies will be overridden: + +``` +"@appium/support": "npm:7.2.5" +"@appium/types": "npm:1.5.1" +async-lock: "npm:1.4.1" -> "npm:^1.4.1" +asyncbox: "npm:6.3.0" -> "npm:^6.3.0" +axios: "npm:1.18.0" -> "npm:^1.18.0" +``` + +Note that `@appium` packages are untouched. The plugin will try to detect +inter-dependencies and leave them alone. + +If you want to use a different specifier than `^`, you can configure it like +below: + +```yml +dynamicPackageOverrides: + - id: "@appium/base-driver" + specifier: "~" +``` diff --git a/incubator/yarn-plugin-dynamic-overrides/index.js b/incubator/yarn-plugin-dynamic-overrides/index.js new file mode 100644 index 000000000..410cdad45 --- /dev/null +++ b/incubator/yarn-plugin-dynamic-overrides/index.js @@ -0,0 +1,118 @@ +// @ts-check + +/** + * @import { Descriptor, Hooks, Ident, Plugin } from "@yarnpkg/core"; + * + * @typedef {Ident & { specifier: string; }} ExtendedIdent + */ + +const DEFAULT_SPECIFIER = "^"; +const DYNAMIC_OVERRIDES_KEY = "dynamicPackageOverrides"; + +/** + * @param {Descriptor} dependency + * @param {Ident=} locator + * @returns {locator is Ident} + */ +function matches(dependency, locator) { + if (!locator) { + return false; + } + + // appium -> @appium/base-plugin + if (locator.name === dependency.scope) { + return false; + } + + // @appium/base-plugin -> @appium/base-driver + if (locator.scope && locator.scope === dependency.scope) { + return false; + } + + return true; +} + +// This module *must* be CommonJS because `actions/setup-node` (and probably +// other GitHub actions) does not support ESM. Yarn itself does. +exports.name = "@rnx-kit/yarn-plugin-dynamic-overrides"; + +/** @type {(require: NodeJS.Require) => Plugin} */ +exports.factory = (require) => { + const { SettingsType, structUtils } = require("@yarnpkg/core"); + + /** + * @param {Map} entry + * @returns {[string, ExtendedIdent]} + */ + function toKeyValuePair(entry) { + const id = entry.get("id"); + if (!id) { + throw new Error(`"${DYNAMIC_OVERRIDES_KEY}" expects an id`); + } + const ident = structUtils.parseIdent(id); + return [ + ident.identHash, + { + ...ident, + specifier: entry.get("specifier") ?? DEFAULT_SPECIFIER, + }, + ]; + } + + /** @type {Plugin["configuration"] & Record} */ + const configuration = {}; + configuration[DYNAMIC_OVERRIDES_KEY] = { + description: "Packages whose dependencies are overridden", + type: SettingsType.SHAPE, + isArray: true, + properties: { + id: { + type: SettingsType.STRING, + }, + specifier: { + type: SettingsType.STRING, + default: DEFAULT_SPECIFIER, + }, + }, + }; + + /** @type {Map} */ + let overrides; + + return { + configuration, + hooks: { + reduceDependency: async ( + dependency, + project, + locator, + _initialDependency, + _extra + ) => { + if (!overrides) { + const config = project.configuration.get(DYNAMIC_OVERRIDES_KEY); + if (!Array.isArray(config)) { + throw new Error( + `Expected "${DYNAMIC_OVERRIDES_KEY}" to be an array` + ); + } + overrides = new Map(config.map(toKeyValuePair)); + } + + const ident = overrides.get(locator.identHash); + if (matches(dependency, ident)) { + const { protocol, selector } = structUtils.parseRange( + dependency.range + ); + if (protocol === "npm:" && /^\d/.test(selector)) { + return structUtils.makeDescriptor( + dependency, + `${protocol}${ident.specifier}${selector}` + ); + } + } + return dependency; + }, + }, + }; +}; diff --git a/incubator/yarn-plugin-dynamic-overrides/package.json b/incubator/yarn-plugin-dynamic-overrides/package.json new file mode 100644 index 000000000..b7802a542 --- /dev/null +++ b/incubator/yarn-plugin-dynamic-overrides/package.json @@ -0,0 +1,40 @@ +{ + "name": "@rnx-kit/yarn-plugin-dynamic-overrides", + "version": "0.0.1", + "private": true, + "description": "EXPERIMENTAL - USE WITH CAUTION - yarn-plugin-dynamic-overrides", + "homepage": "https://github.com/microsoft/rnx-kit/tree/main/incubator/yarn-plugin-dynamic-overrides#readme", + "license": "MIT", + "author": { + "name": "Microsoft Open Source", + "email": "microsoftopensource@users.noreply.github.com" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/rnx-kit", + "directory": "incubator/yarn-plugin-dynamic-overrides" + }, + "files": [ + "index.js" + ], + "main": "index.js", + "exports": { + ".": "./index.js" + }, + "scripts": { + "build": "rnx-kit-scripts build", + "format": "rnx-kit-scripts format", + "lint": "rnx-kit-scripts lint", + "test": "rnx-kit-scripts test" + }, + "devDependencies": { + "@rnx-kit/scripts": "*", + "@rnx-kit/tsconfig": "*", + "@yarnpkg/core": "^4.0.0" + }, + "engines": { + "node": ">=20.18", + "yarn": ">=4.0" + }, + "experimental": true +} diff --git a/incubator/yarn-plugin-dynamic-overrides/tsconfig.json b/incubator/yarn-plugin-dynamic-overrides/tsconfig.json new file mode 100644 index 000000000..c2525141f --- /dev/null +++ b/incubator/yarn-plugin-dynamic-overrides/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@rnx-kit/tsconfig/tsconfig.nodenext.json", + "compilerOptions": { + "noEmit": true + }, + "include": ["index.js"] +} diff --git a/package.json b/package.json index 945231e32..3cd9a02e5 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "@react-native-windows/telemetry/@xmldom/xmldom": "^0.8.13", "@rnx-kit/react-native-host": "workspace:*", "node-gyp": "ignore:", - "nx/minimatch": "^10.2.4", "react-native-windows/@react-native-community/cli": "^20.0.0", "react-native-windows/@react-native-community/cli-platform-android": "^20.0.0", "react-native-windows/@react-native-community/cli-platform-ios": "^20.0.0" diff --git a/yarn.lock b/yarn.lock index 00df7d813..5a12a82f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1834,31 +1834,31 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.1.0": - version: 1.8.1 - resolution: "@emnapi/core@npm:1.8.1" +"@emnapi/core@npm:^1.4.3": + version: 1.11.2 + resolution: "@emnapi/core@npm:1.11.2" dependencies: - "@emnapi/wasi-threads": "npm:1.1.0" + "@emnapi/wasi-threads": "npm:1.2.2" tslib: "npm:^2.4.0" - checksum: 10c0/2c242f4b49779bac403e1cbcc98edacdb1c8ad36562408ba9a20663824669e930bc8493be46a2522d9dc946b8d96cd7073970bae914928c7671b5221c85b432e + checksum: 10c0/424ca1607f498e524eb58db1095e6cc2082986edfd84a74b116d4e2c6e43b5e9d557ea7f0d7b9adf7f6d5023e25ac2ed6bd08caf0043d3d8602598d79579c2cd languageName: node linkType: hard -"@emnapi/runtime@npm:^1.1.0": - version: 1.8.1 - resolution: "@emnapi/runtime@npm:1.8.1" +"@emnapi/runtime@npm:^1.4.3": + version: 1.11.2 + resolution: "@emnapi/runtime@npm:1.11.2" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/f4929d75e37aafb24da77d2f58816761fe3f826aad2e37fa6d4421dac9060cbd5098eea1ac3c9ecc4526b89deb58153852fa432f87021dc57863f2ff726d713f + checksum: 10c0/d8d500059fe9c0864571c79ce29439c1b6fb44d7ec4ac865a2aaaa7469194e5d91ebdc820cabd37c3d373478b725a8b60771733e4743cfef41fc86d9a1f2eab0 languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.1.0": - version: 1.1.0 - resolution: "@emnapi/wasi-threads@npm:1.1.0" +"@emnapi/wasi-threads@npm:1.2.2": + version: 1.2.2 + resolution: "@emnapi/wasi-threads@npm:1.2.2" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 + checksum: 10c0/f0dc8269d6b20ae5a7c7b36e7a6a333452009d461038ef4febb29da2f3f78c1e2b1576d7e8970a5c5789ed3caedc1f80f5b0c2a5373bdaf8d03b20432bb55747 languageName: node linkType: hard @@ -2967,14 +2967,14 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:0.2.4": - version: 0.2.4 - resolution: "@napi-rs/wasm-runtime@npm:0.2.4" +"@napi-rs/wasm-runtime@npm:^0.2.4": + version: 0.2.12 + resolution: "@napi-rs/wasm-runtime@npm:0.2.12" dependencies: - "@emnapi/core": "npm:^1.1.0" - "@emnapi/runtime": "npm:^1.1.0" - "@tybys/wasm-util": "npm:^0.9.0" - checksum: 10c0/1040de49b2ef509db207e2517465dbf7fb3474f20e8ec32897672a962ff4f59872385666dac61dc9dbeae3cae5dad265d8dc3865da756adeb07d1634c67b03a1 + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.10.0" + checksum: 10c0/6d07922c0613aab30c6a497f4df297ca7c54e5b480e00035e0209b872d5c6aab7162fc49477267556109c2c7ed1eb9c65a174e27e9b87568106a87b0a6e3ca7d languageName: node linkType: hard @@ -6223,6 +6223,16 @@ __metadata: languageName: unknown linkType: soft +"@rnx-kit/yarn-plugin-dynamic-overrides@workspace:incubator/yarn-plugin-dynamic-overrides": + version: 0.0.0-use.local + resolution: "@rnx-kit/yarn-plugin-dynamic-overrides@workspace:incubator/yarn-plugin-dynamic-overrides" + dependencies: + "@rnx-kit/scripts": "npm:*" + "@rnx-kit/tsconfig": "npm:*" + "@yarnpkg/core": "npm:^4.0.0" + languageName: unknown + linkType: soft + "@rnx-kit/yarn-plugin-external-workspaces@workspace:incubator/yarn-plugin-external-workspaces": version: 0.0.0-use.local resolution: "@rnx-kit/yarn-plugin-external-workspaces@workspace:incubator/yarn-plugin-external-workspaces" @@ -6625,21 +6635,12 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.1": - version: 0.10.1 - resolution: "@tybys/wasm-util@npm:0.10.1" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 - languageName: node - linkType: hard - -"@tybys/wasm-util@npm:^0.9.0": - version: 0.9.0 - resolution: "@tybys/wasm-util@npm:0.9.0" +"@tybys/wasm-util@npm:^0.10.0, @tybys/wasm-util@npm:^0.10.1": + version: 0.10.3 + resolution: "@tybys/wasm-util@npm:0.10.3" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d + checksum: 10c0/fd2bd2a79c6cd8c79ed1cf7a0fa375c64589264c88a27acaf9756d556b453ea222b62a4f68dd2fbb8b3a78b6bab3b1f4fb2431b6afc6aeda8344b53a521a1cd3 languageName: node linkType: hard @@ -7443,17 +7444,7 @@ __metadata: languageName: node linkType: hard -"@yarnpkg/parsers@npm:3.0.2": - version: 3.0.2 - resolution: "@yarnpkg/parsers@npm:3.0.2" - dependencies: - js-yaml: "npm:^3.10.0" - tslib: "npm:^2.4.0" - checksum: 10c0/a0c340e13129643162423d7e666061c0b39b143bfad3fc5a74c7d92a30fd740f6665d41cd4e61832c20375889d793eea1d1d103cacb39ed68f7acd168add8c53 - languageName: node - linkType: hard - -"@yarnpkg/parsers@npm:^3.0.3": +"@yarnpkg/parsers@npm:^3.0.2, @yarnpkg/parsers@npm:^3.0.3": version: 3.0.3 resolution: "@yarnpkg/parsers@npm:3.0.3" dependencies: @@ -7908,7 +7899,7 @@ __metadata: languageName: node linkType: hard -"@zkochan/js-yaml@npm:0.0.7": +"@zkochan/js-yaml@npm:^0.0.7": version: 0.0.7 resolution: "@zkochan/js-yaml@npm:0.0.7" dependencies: @@ -8929,15 +8920,6 @@ __metadata: languageName: node linkType: hard -"cli-cursor@npm:3.1.0, cli-cursor@npm:^3.1.0": - version: 3.1.0 - resolution: "cli-cursor@npm:3.1.0" - dependencies: - restore-cursor: "npm:^3.1.0" - checksum: 10c0/92a2f98ff9037d09be3dfe1f0d749664797fb674bf388375a2207a1203b69d41847abf16434203e0089212479e47a358b13a0222ab9fccfe8e2644a7ccebd111 - languageName: node - linkType: hard - "cli-cursor@npm:^2.1.0": version: 2.1.0 resolution: "cli-cursor@npm:2.1.0" @@ -8947,6 +8929,15 @@ __metadata: languageName: node linkType: hard +"cli-cursor@npm:^3.1.0": + version: 3.1.0 + resolution: "cli-cursor@npm:3.1.0" + dependencies: + restore-cursor: "npm:^3.1.0" + checksum: 10c0/92a2f98ff9037d09be3dfe1f0d749664797fb674bf388375a2207a1203b69d41847abf16434203e0089212479e47a358b13a0222ab9fccfe8e2644a7ccebd111 + languageName: node + linkType: hard + "cli-cursor@npm:^5.0.0": version: 5.0.0 resolution: "cli-cursor@npm:5.0.0" @@ -8956,14 +8947,7 @@ __metadata: languageName: node linkType: hard -"cli-spinners@npm:2.6.1": - version: 2.6.1 - resolution: "cli-spinners@npm:2.6.1" - checksum: 10c0/6abcdfef59aa68e6b51376d87d257f9120a0a7120a39dd21633702d24797decb6dc747dff2217c88732710db892b5053c5c672d221b6c4d13bbcb5372e203596 - languageName: node - linkType: hard - -"cli-spinners@npm:^2.0.0, cli-spinners@npm:^2.2.0, cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.9.2": +"cli-spinners@npm:^2.0.0, cli-spinners@npm:^2.2.0, cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.6.1, cli-spinners@npm:^2.9.2": version: 2.9.2 resolution: "cli-spinners@npm:2.9.2" checksum: 10c0/907a1c227ddf0d7a101e7ab8b300affc742ead4b4ebe920a5bf1bc6d45dce2958fcd195eb28fa25275062fe6fa9b109b93b63bc8033396ed3bcb50297008b3a3 @@ -10584,7 +10568,7 @@ __metadata: languageName: node linkType: hard -"figures@npm:3.2.0": +"figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" dependencies: @@ -12725,10 +12709,10 @@ __metadata: languageName: node linkType: hard -"jsonc-parser@npm:3.2.0": - version: 3.2.0 - resolution: "jsonc-parser@npm:3.2.0" - checksum: 10c0/5a12d4d04dad381852476872a29dcee03a57439574e4181d91dca71904fcdcc5e8e4706c0a68a2c61ad9810e1e1c5806b5100d52d3e727b78f5cdc595401045b +"jsonc-parser@npm:^3.2.0": + version: 3.3.1 + resolution: "jsonc-parser@npm:3.3.1" + checksum: 10c0/269c3ae0a0e4f907a914bf334306c384aabb9929bd8c99f909275ebd5c2d3bc70b9bcd119ad794f339dec9f24b6a4ee9cd5a8ab2e6435e730ad4075388fc2ab6 languageName: node linkType: hard @@ -12849,13 +12833,6 @@ __metadata: languageName: node linkType: hard -"lines-and-columns@npm:2.0.3": - version: 2.0.3 - resolution: "lines-and-columns@npm:2.0.3" - checksum: 10c0/09525c10010a925b7efe858f1dd3184eeac34f0a9bc34993075ec490efad71e948147746b18e9540279cc87cd44085b038f986903db3de65ffe96d38a7b91c4c - languageName: node - linkType: hard - "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -12863,6 +12840,13 @@ __metadata: languageName: node linkType: hard +"lines-and-columns@npm:^2.0.3": + version: 2.0.4 + resolution: "lines-and-columns@npm:2.0.4" + checksum: 10c0/4db28bf065cd7ad897c0700f22d3d0d7c5ed6777e138861c601c496d545340df3fc19e18bd04ff8d95a246a245eb55685b82ca2f8c2ca53a008e9c5316250379 + languageName: node + linkType: hard + "linkify-it@npm:^5.0.2": version: 5.0.2 resolution: "linkify-it@npm:5.0.2" @@ -12953,7 +12937,7 @@ __metadata: languageName: node linkType: hard -"log-symbols@npm:^4.0.0, log-symbols@npm:^4.1.0": +"log-symbols@npm:^4.1.0": version: 4.1.0 resolution: "log-symbols@npm:4.1.0" dependencies: @@ -14004,7 +13988,7 @@ __metadata: languageName: node linkType: hard -"node-machine-id@npm:1.1.12": +"node-machine-id@npm:^1.1.12": version: 1.1.12 resolution: "node-machine-id@npm:1.1.12" checksum: 10c0/ab2fea5f75a6f1ce3c76c5e0ae3903b631230e0a99b003d176568fff8ddbdf7b2943be96cd8d220c497ca0f6149411831f8a450601929f326781cb1b59bab7f8 @@ -14451,22 +14435,6 @@ __metadata: languageName: node linkType: hard -"ora@npm:5.3.0": - version: 5.3.0 - resolution: "ora@npm:5.3.0" - dependencies: - bl: "npm:^4.0.3" - chalk: "npm:^4.1.0" - cli-cursor: "npm:^3.1.0" - cli-spinners: "npm:^2.5.0" - is-interactive: "npm:^1.0.0" - log-symbols: "npm:^4.0.0" - strip-ansi: "npm:^6.0.0" - wcwidth: "npm:^1.0.1" - checksum: 10c0/30d5f3218eb75b0a2028c5fb9aa88e83e38a2f1745ab56839abb06c3ba31bae35f768f4e72c4f9e04e2a66be6a898e9312e8cf85c9333e1e3613eabb8c7cdf57 - languageName: node - linkType: hard - "ora@npm:^3.4.0": version: 3.4.0 resolution: "ora@npm:3.4.0" @@ -14481,7 +14449,7 @@ __metadata: languageName: node linkType: hard -"ora@npm:^5.4.1": +"ora@npm:^5.3.0, ora@npm:^5.4.1": version: 5.4.1 resolution: "ora@npm:5.4.1" dependencies: @@ -16108,7 +16076,7 @@ __metadata: languageName: node linkType: hard -"resolve.exports@npm:2.0.3, resolve.exports@npm:^2.0.0": +"resolve.exports@npm:^2.0.0, resolve.exports@npm:^2.0.3": version: 2.0.3 resolution: "resolve.exports@npm:2.0.3" checksum: 10c0/1ade1493f4642a6267d0a5e68faeac20b3d220f18c28b140343feb83694d8fed7a286852aef43689d16042c61e2ddb270be6578ad4a13990769e12065191200d @@ -18094,13 +18062,6 @@ __metadata: languageName: node linkType: hard -"yargs-parser@npm:21.1.1, yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 - languageName: node - linkType: hard - "yargs-parser@npm:^18.1.2": version: 18.1.3 resolution: "yargs-parser@npm:18.1.3" @@ -18118,6 +18079,13 @@ __metadata: languageName: node linkType: hard +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 + languageName: node + linkType: hard + "yargs-parser@npm:^22.0.0": version: 22.0.0 resolution: "yargs-parser@npm:22.0.0"