From eaa750013030827b065dc7ba3ca1b6a2ed2d645f Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 9 Apr 2024 21:12:35 +0100 Subject: [PATCH 01/13] yarn-plugin: add initial version of plugin Signed-off-by: MT Lewis --- packages/yarn-plugin/.eslintrc.js | 1 + packages/yarn-plugin/README.md | 12 + packages/yarn-plugin/catalog-info.yaml | 10 + packages/yarn-plugin/package.json | 42 + packages/yarn-plugin/src/index.ts | 23 + .../src/resolver/BackstageResolver.ts | 86 ++ yarn.lock | 1162 ++++++++++++++++- 7 files changed, 1289 insertions(+), 47 deletions(-) create mode 100644 packages/yarn-plugin/.eslintrc.js create mode 100644 packages/yarn-plugin/README.md create mode 100644 packages/yarn-plugin/catalog-info.yaml create mode 100644 packages/yarn-plugin/package.json create mode 100644 packages/yarn-plugin/src/index.ts create mode 100644 packages/yarn-plugin/src/resolver/BackstageResolver.ts diff --git a/packages/yarn-plugin/.eslintrc.js b/packages/yarn-plugin/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/yarn-plugin/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/yarn-plugin/README.md b/packages/yarn-plugin/README.md new file mode 100644 index 0000000000..dc3e509872 --- /dev/null +++ b/packages/yarn-plugin/README.md @@ -0,0 +1,12 @@ +# yarn-plugin-backstage + +This yarn plugin adds a `backstage:` version protocol to yarn, which replaces +specific version ranges for `@backstage/` packages. The recommended mode of use +is to set all versions strings to `backstage:*` in package.json, which causes +all versions to be resolved based on the version of Backstage specified in +`backstage.json`. This ensures that all `@backstage/` packages always correspond +to a single release, and removes the need for `package.json` files +to change when upgrading to a new release. + +**This plugin is still under active development, and requires some further +testing before we recommend it for general use.** diff --git a/packages/yarn-plugin/catalog-info.yaml b/packages/yarn-plugin/catalog-info.yaml new file mode 100644 index 0000000000..c3a9be8fa5 --- /dev/null +++ b/packages/yarn-plugin/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: yarn-plugin-backstage + title: yarn-plugin-backstage + description: Yarn plugin for working with Backstage monorepos +spec: + lifecycle: experimental + type: backstage-node-library + owner: maintainers diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json new file mode 100644 index 0000000000..713d7e5c49 --- /dev/null +++ b/packages/yarn-plugin/package.json @@ -0,0 +1,42 @@ +{ + "name": "yarn-plugin-backstage", + "description": "Yarn plugin for working with Backstage monorepos", + "version": "0.0.0", + "private": true, + "backstage": { + "role": "node-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "packages/yarn-plugin" + }, + "keywords": [ + "backstage" + ], + "license": "Apache-2.0", + "main": "./src/index.ts", + "scripts": { + "build": "builder build plugin", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "start": "nodemon --" + }, + "dependencies": { + "@backstage/release-manifests": "workspace:^", + "@yarnpkg/core": "^4.0.3", + "@yarnpkg/fslib": "^3.0.2" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@yarnpkg/builder": "^4.0.0", + "nodemon": "^3.0.1" + }, + "nodemonConfig": { + "watch": "./src", + "exec": "builder build plugin", + "ext": "ts" + } +} diff --git a/packages/yarn-plugin/src/index.ts b/packages/yarn-plugin/src/index.ts new file mode 100644 index 0000000000..ce12c836dd --- /dev/null +++ b/packages/yarn-plugin/src/index.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Plugin } from '@yarnpkg/core'; +import { BackstageResolver } from './resolver/BackstageResolver'; + +const plugin: Plugin = { + resolvers: [BackstageResolver], +}; + +export default plugin; diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts new file mode 100644 index 0000000000..5c227d84e4 --- /dev/null +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + structUtils, + Descriptor, + Locator, + Package, + Resolver, +} from '@yarnpkg/core'; +import { xfs, npath } from '@yarnpkg/fslib'; +import { getManifestByVersion } from '@backstage/release-manifests'; + +export class BackstageResolver implements Resolver { + static protocol = `backstage:`; + + supportsDescriptor = (descriptor: Descriptor) => + descriptor.range.startsWith(BackstageResolver.protocol); + + shouldPersistResolution = () => true; + + bindDescriptor(descriptor: Descriptor): Descriptor { + if (descriptor.range === `${BackstageResolver.protocol}*`) { + const backstageJson = xfs.readJsonSync( + npath.toPortablePath('./backstage.json'), + ); + + return structUtils.makeDescriptor( + descriptor, + `backstage:${backstageJson.version}`, + ); + } + + return descriptor; + } + + async getCandidates(descriptor: Descriptor): Promise { + const backstageVersion = descriptor.range.replace( + BackstageResolver.protocol, + '', + ); + + const manifest = await getManifestByVersion({ version: backstageVersion }); + const ident = structUtils.stringifyIdent(descriptor); + + const manifestEntry = manifest.packages.find( + candidate => candidate.name === ident, + ); + + if (!manifestEntry) { + throw new Error(`Package ${ident} not found in manifest`); + } + + return [ + structUtils.makeLocator(descriptor, `npm:${manifestEntry.version}`), + ]; + } + + supportsLocator = () => false; + + getResolutionDependencies = () => ({}); + + async getSatisfying(): Promise<{ locators: Locator[]; sorted: boolean }> { + // Candidate versions produced by this resolver always use the `npm:` + // protocol, so this function will never be called. + throw new Error('Unreachable'); + } + + async resolve(): Promise { + // Once transformed into locators (through getCandidates), the versions are + // resolved by the NpmSemverResolver + throw new Error(`Unreachable`); + } +} diff --git a/yarn.lock b/yarn.lock index 5bec6d68de..8b8caa5875 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,6 +19,157 @@ __metadata: languageName: node linkType: hard +"@algolia/cache-browser-local-storage@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/cache-browser-local-storage@npm:4.23.2" + dependencies: + "@algolia/cache-common": 4.23.2 + checksum: 3b6b09666ba38f3675927f8193928e168becbb77fd3f0b27d1f7a94540be81c9837950c9e82a08502f48cff36938602ff8067575e6c12aea3869525ea3dcf69a + languageName: node + linkType: hard + +"@algolia/cache-common@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/cache-common@npm:4.23.2" + checksum: 45cbf8feafbd13219982c178c3173c22f836e7d1b4bfc87ce346e7d6a565d45c822b3ad301afec120a1131f91f31f9c078ae897b917885277a952a9cc67515e2 + languageName: node + linkType: hard + +"@algolia/cache-in-memory@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/cache-in-memory@npm:4.23.2" + dependencies: + "@algolia/cache-common": 4.23.2 + checksum: a89ed4320e94825effd647124fdfef18a2beee3942efa7fe865d071be04de096a8b3835cd0d872ba349681770ce9c8cf12720b9f74b0124db67b715f64c6a8fa + languageName: node + linkType: hard + +"@algolia/client-account@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/client-account@npm:4.23.2" + dependencies: + "@algolia/client-common": 4.23.2 + "@algolia/client-search": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: fa180f2c9c25e455d3094627586fc880c1b88c5bb0eba7ce663792d416d887f35108202e2a7279abd4a3df7c75bf0ef7fe63c21243fe7324970b350e654a0471 + languageName: node + linkType: hard + +"@algolia/client-analytics@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/client-analytics@npm:4.23.2" + dependencies: + "@algolia/client-common": 4.23.2 + "@algolia/client-search": 4.23.2 + "@algolia/requester-common": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: 51302bf7dbdfd97a88e4a181649d09a848f8b8a167ef55a0f951f00e3091f01c27aa8541698ef08fe029d36558447e983361bef880522c1ccc18e852db2a905c + languageName: node + linkType: hard + +"@algolia/client-common@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/client-common@npm:4.23.2" + dependencies: + "@algolia/requester-common": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: 0d36e794e682794d8831a2a92050a8fdd4f9a50e80debd41f608b4401c61fc9c96ec68b23385c474b34cc6bc2dc9468e418c07274878507e8fabdf73dd534322 + languageName: node + linkType: hard + +"@algolia/client-personalization@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/client-personalization@npm:4.23.2" + dependencies: + "@algolia/client-common": 4.23.2 + "@algolia/requester-common": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: b8fc0fe3922f8db8b13572d3eb4f472defa277261e5cbf6b01d1a59ff470b88380f1b569c3abb25e43ec1abdcfd276c199ffd336464904cdfa65a346e309853e + languageName: node + linkType: hard + +"@algolia/client-search@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/client-search@npm:4.23.2" + dependencies: + "@algolia/client-common": 4.23.2 + "@algolia/requester-common": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: e8eee05b362c84b33a7f4ba5e3af5274a3b4dde9cf20d4c755dce0f31715495f982574c84cc98f6b67d92229a06f9d5f9588b4d8659413131d4a589a3bd9a3f4 + languageName: node + linkType: hard + +"@algolia/logger-common@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/logger-common@npm:4.23.2" + checksum: da3c48adce896c91dd7a9770f8e6378394d4c7f0cd6f50710d340e411be0c8c52cd731488822ebec2926d2cbba7d0674dead23255f43bdf3f811f10a68c80f5e + languageName: node + linkType: hard + +"@algolia/logger-console@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/logger-console@npm:4.23.2" + dependencies: + "@algolia/logger-common": 4.23.2 + checksum: d3c82c5a6a15399621898bf8206a636be0c7edab59c22fd48c2590d77804365266a87e721b6ceee9ff97a8e5a7cd1b9353cf56dd7b3ac31b5ff36e7634decd13 + languageName: node + linkType: hard + +"@algolia/recommend@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/recommend@npm:4.23.2" + dependencies: + "@algolia/cache-browser-local-storage": 4.23.2 + "@algolia/cache-common": 4.23.2 + "@algolia/cache-in-memory": 4.23.2 + "@algolia/client-common": 4.23.2 + "@algolia/client-search": 4.23.2 + "@algolia/logger-common": 4.23.2 + "@algolia/logger-console": 4.23.2 + "@algolia/requester-browser-xhr": 4.23.2 + "@algolia/requester-common": 4.23.2 + "@algolia/requester-node-http": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: fa2b81656ac9aa557e06b57b3acde558d29da84ce45fddbe083145ec22cc540653f24436df2ecd24ffcfaf7c6115862833e76f6e745dad64b19a5a4a8aa36330 + languageName: node + linkType: hard + +"@algolia/requester-browser-xhr@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/requester-browser-xhr@npm:4.23.2" + dependencies: + "@algolia/requester-common": 4.23.2 + checksum: a16bdcebac7febd82052fab2bb9caef6c3e84a94092c0b70f2ea3aefff825099f6c6aa02bfeaacff6c5157e3bb89bfcfd690746e34aeb988272d64c4e31fb560 + languageName: node + linkType: hard + +"@algolia/requester-common@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/requester-common@npm:4.23.2" + checksum: a57da6b4a675b2176aa66d3148939e023f8fb2eb1e0a8830e4e07d2ecf4edae3416ee8614dd5bae4b8a1fc40fc3a418db24180a6a9cc64b227312e00512fc456 + languageName: node + linkType: hard + +"@algolia/requester-node-http@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/requester-node-http@npm:4.23.2" + dependencies: + "@algolia/requester-common": 4.23.2 + checksum: 3085543774fbdf77f043d22ec9528815408e103a9c628f84c702338f16bcbd1cf818d70c7fcb3a11c4542e5b264c56a7e30840c56fd895c5645f72ba16808fc8 + languageName: node + linkType: hard + +"@algolia/transporter@npm:4.23.2": + version: 4.23.2 + resolution: "@algolia/transporter@npm:4.23.2" + dependencies: + "@algolia/cache-common": 4.23.2 + "@algolia/logger-common": 4.23.2 + "@algolia/requester-common": 4.23.2 + checksum: 8ac57c003e6c5ab39c0cd873c325746c90e6bdbe0857c4157b551678cc4efed48e9423317dfced722d094810649d1ae44210c98122d6c1bece35713adffd2b24 + languageName: node + linkType: hard + "@ampproject/remapping@npm:^2.2.0": version: 2.2.1 resolution: "@ampproject/remapping@npm:2.2.1" @@ -105,6 +256,15 @@ __metadata: languageName: node linkType: hard +"@arcanis/slice-ansi@npm:^1.1.1": + version: 1.1.1 + resolution: "@arcanis/slice-ansi@npm:1.1.1" + dependencies: + grapheme-splitter: ^1.0.4 + checksum: 14ed60cb45750d386c64229ac7bab20e10eedc193503fa4decff764162d329d6d3363ed2cd3debec833186ee54affe4f824f6e8eff531295117fd1ebda200270 + languageName: node + linkType: hard + "@ardatan/sync-fetch@npm:^0.0.1": version: 0.0.1 resolution: "@ardatan/sync-fetch@npm:0.0.1" @@ -17112,6 +17272,13 @@ __metadata: languageName: node linkType: hard +"@types/emscripten@npm:^1.39.6": + version: 1.39.10 + resolution: "@types/emscripten@npm:1.39.10" + checksum: 1721da76593f9194e0b7c90a581e2d31c23bd4eb28f93030cd1dc58216cdf1e692c045274f2eedaed29c652c25c9a4dff2e503b11bd1258d07095c009a1956b1 + languageName: node + linkType: hard + "@types/es-aggregate-error@npm:^1.0.2": version: 1.0.2 resolution: "@types/es-aggregate-error@npm:1.0.2" @@ -17815,12 +17982,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^18.17.8": - version: 18.19.8 - resolution: "@types/node@npm:18.19.8" +"@types/node@npm:^18.17.15, @types/node@npm:^18.17.8": + version: 18.19.31 + resolution: "@types/node@npm:18.19.31" dependencies: undici-types: ~5.26.4 - checksum: fa291495d6157a9d9393b4c3bdbf1ce12a8f661dc9da6a4fa19bcdb19af1c62bb8dbf7fb66ae135f29cd788b618e9845b83e9c47edcf39f0953a8561fdacd9a3 + checksum: 949bddfd7071bd47300d1f33d380ee34695ccd5f046f1a03e4d2be0d953ace896905144d44a6f483f241b5ef34b86f0e40a0e312201117782eecf89e81a4ff13 languageName: node linkType: hard @@ -18238,7 +18405,7 @@ __metadata: languageName: node linkType: hard -"@types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": +"@types/semver@npm:^7.1.0, @types/semver@npm:^7.3.12, @types/semver@npm:^7.5.0": version: 7.5.8 resolution: "@types/semver@npm:7.5.8" checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 @@ -18473,6 +18640,13 @@ __metadata: languageName: node linkType: hard +"@types/treeify@npm:^1.0.0": + version: 1.0.3 + resolution: "@types/treeify@npm:1.0.3" + checksum: 777e579b30a916a781e7cbad2b7a76bc5473ff7bfe7167dd6de47f80f4386df5bf3d0dc34170afb75d52e75f6ed61cc109abf2324e093c1f9ecd4e79fec58d0c + languageName: node + linkType: hard + "@types/triple-beam@npm:^1.3.2": version: 1.3.2 resolution: "@types/triple-beam@npm:1.3.2" @@ -18628,6 +18802,13 @@ __metadata: languageName: node linkType: hard +"@types/yoga-layout@npm:1.9.2": + version: 1.9.2 + resolution: "@types/yoga-layout@npm:1.9.2" + checksum: dbc3d6ab997d50fe1fcca5dd6822982c8fe586145ab648e0e97c3bc4ebc93d0b40c9edd75febaba374d61f60c1379b639f6be652965c776a901bf1068f2eac87 + languageName: node + linkType: hard + "@types/yup@npm:^0.32.0": version: 0.32.0 resolution: "@types/yup@npm:0.32.0" @@ -19312,6 +19493,144 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/builder@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/builder@npm:4.0.0" + dependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + "@yarnpkg/fslib": ^3.0.0 + chalk: ^3.0.0 + clipanion: ^4.0.0-rc.2 + esbuild: "npm:esbuild-wasm@^0.15.15" + semver: ^7.1.2 + tslib: ^2.4.0 + bin: + builder: ./lib/cli.js + checksum: 2bc2901e410e5951820c2d6fc5365ab15373b89e9f0aabce96cd6385019983d8911d495e95a4f3b927a1e18bc4b8de2e43158d9319e9a56de44d6e1ae4af9897 + languageName: node + linkType: hard + +"@yarnpkg/cli@npm:^4.0.0": + version: 4.1.1 + resolution: "@yarnpkg/cli@npm:4.1.1" + dependencies: + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/libzip": ^3.0.1 + "@yarnpkg/parsers": ^3.0.0 + "@yarnpkg/plugin-compat": ^4.0.3 + "@yarnpkg/plugin-constraints": ^4.0.2 + "@yarnpkg/plugin-dlx": ^4.0.0 + "@yarnpkg/plugin-essentials": ^4.1.1 + "@yarnpkg/plugin-exec": ^3.0.0 + "@yarnpkg/plugin-file": ^3.0.0 + "@yarnpkg/plugin-git": ^3.0.0 + "@yarnpkg/plugin-github": ^3.0.0 + "@yarnpkg/plugin-http": ^3.0.1 + "@yarnpkg/plugin-init": ^4.0.1 + "@yarnpkg/plugin-interactive-tools": ^4.0.0 + "@yarnpkg/plugin-link": ^3.0.0 + "@yarnpkg/plugin-nm": ^4.0.2 + "@yarnpkg/plugin-npm": ^3.0.1 + "@yarnpkg/plugin-npm-cli": ^4.0.2 + "@yarnpkg/plugin-pack": ^4.0.0 + "@yarnpkg/plugin-patch": ^4.0.1 + "@yarnpkg/plugin-pnp": ^4.0.2 + "@yarnpkg/plugin-pnpm": ^2.0.0 + "@yarnpkg/plugin-stage": ^4.0.0 + "@yarnpkg/plugin-typescript": ^4.0.0 + "@yarnpkg/plugin-version": ^4.0.1 + "@yarnpkg/plugin-workspace-tools": ^4.1.0 + "@yarnpkg/shell": ^4.0.0 + ci-info: ^3.2.0 + clipanion: ^4.0.0-rc.2 + semver: ^7.1.2 + tslib: ^2.4.0 + typanion: ^3.14.0 + peerDependencies: + "@yarnpkg/core": ^4.0.3 + checksum: e16567629195a88b36f744bc6d5b32d7ec5aad7ae37f00607c9ea0175028804ca75cd568a02ae8e28fce431b58fd268a593a13114ad892c2d8ed8f55d2d6768d + languageName: node + linkType: hard + +"@yarnpkg/core@npm:^4.0.0, @yarnpkg/core@npm:^4.0.3": + version: 4.0.3 + resolution: "@yarnpkg/core@npm:4.0.3" + dependencies: + "@arcanis/slice-ansi": ^1.1.1 + "@types/semver": ^7.1.0 + "@types/treeify": ^1.0.0 + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/libzip": ^3.0.1 + "@yarnpkg/parsers": ^3.0.0 + "@yarnpkg/shell": ^4.0.0 + camelcase: ^5.3.1 + chalk: ^3.0.0 + ci-info: ^3.2.0 + clipanion: ^4.0.0-rc.2 + cross-spawn: 7.0.3 + diff: ^5.1.0 + dotenv: ^16.3.1 + fast-glob: ^3.2.2 + got: ^11.7.0 + lodash: ^4.17.15 + micromatch: ^4.0.2 + p-limit: ^2.2.0 + semver: ^7.1.2 + strip-ansi: ^6.0.0 + tar: ^6.0.5 + tinylogic: ^2.0.0 + treeify: ^1.1.0 + tslib: ^2.4.0 + tunnel: ^0.0.6 + checksum: 811956ab94e9f4b3601f304312baf816322df124cf85754ef3985110c90935b1b761c8266a06c2c5633f6edc39c8a4ceffeff50f08f036d7adf19612ce3761a3 + languageName: node + linkType: hard + +"@yarnpkg/extensions@npm:^2.0.1": + version: 2.0.1 + resolution: "@yarnpkg/extensions@npm:2.0.1" + peerDependencies: + "@yarnpkg/core": ^4.0.3 + checksum: e578718513822644b0857adece75dd7a7eea5cd4106ccd5cf37bfa11d8ad04051a0f4c339d0077fe6ec7f9a769d5e782f3034f4219e2a4bc3d54087aacbcdaf6 + languageName: node + linkType: hard + +"@yarnpkg/fslib@npm:^3.0.0, @yarnpkg/fslib@npm:^3.0.1, @yarnpkg/fslib@npm:^3.0.2": + version: 3.0.2 + resolution: "@yarnpkg/fslib@npm:3.0.2" + dependencies: + tslib: ^2.4.0 + checksum: b0795df777e43eb1c2bd8aa1d6c45f88b8a1d3922ee8bf264cdca916cc6f9455551a9499761a9c1f585aa576350d84adcc315e497fc031cdbbbc1a5c71942e1b + languageName: node + linkType: hard + +"@yarnpkg/libui@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/libui@npm:3.0.0" + dependencies: + tslib: ^2.4.0 + peerDependencies: + ink: ^3.0.8 + react: ^16.8.4 + checksum: 66a0f117ee35736012aa9fbaca68e62ef0c4b1731cff3f851aabb901366aa37102186cdf2917ee73ad8c99e54f78864b9274ef49b7b90552451a8d726c2d08ae + languageName: node + linkType: hard + +"@yarnpkg/libzip@npm:^3.0.0, @yarnpkg/libzip@npm:^3.0.1": + version: 3.0.1 + resolution: "@yarnpkg/libzip@npm:3.0.1" + dependencies: + "@types/emscripten": ^1.39.6 + "@yarnpkg/fslib": ^3.0.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/fslib": ^3.0.2 + checksum: 932b1fc35bb60ca57d033aab7a940f7b1d7bf52a68bfff6c755fe26827c0f1b373fda33e373afabbae98de3ed31ae4f0e9ee2ef24588cd074b75fb814117827d + languageName: node + linkType: hard + "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -19319,6 +19638,17 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/nm@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/nm@npm:4.0.2" + dependencies: + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/pnp": ^4.0.2 + checksum: 4a9d1a62d33230c84c3396e84e6b8a25e6b6c3ab9f9f36815b7ecf7581f5bf59abc1996f9ccf583627c177a841d09ffa31ad9cdd48ba3d500263bf12ad1ff281 + languageName: node + linkType: hard + "@yarnpkg/parsers@npm:^3.0.0": version: 3.0.0 resolution: "@yarnpkg/parsers@npm:3.0.0" @@ -19329,6 +19659,414 @@ __metadata: languageName: node linkType: hard +"@yarnpkg/plugin-compat@npm:^4.0.3": + version: 4.0.3 + resolution: "@yarnpkg/plugin-compat@npm:4.0.3" + dependencies: + "@yarnpkg/extensions": ^2.0.1 + peerDependencies: + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-patch": ^4.0.1 + checksum: 0704e4f5d2fd85cf93cbeae88ada3aaec67f390037e166e8dfa04ba1d02780ef169c3d174c2e46b1a8ada5ba3c35dfd5082ff026b638c6ca7b405a6aa7e9453b + languageName: node + linkType: hard + +"@yarnpkg/plugin-constraints@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/plugin-constraints@npm:4.0.2" + dependencies: + "@yarnpkg/fslib": ^3.0.1 + clipanion: ^4.0.0-rc.2 + lodash: ^4.17.15 + tau-prolog: ^0.2.66 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.2 + "@yarnpkg/core": ^4.0.2 + checksum: 9d357906336141d7fc8d6a2a7cf6e62ec4d6c8f8f06b3856286f7473dff2f0a03d1b21c28335b13540528a0cfcb9206062f20d2deeca78d3f3e02f41a1a0150e + languageName: node + linkType: hard + +"@yarnpkg/plugin-dlx@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/plugin-dlx@npm:4.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + clipanion: ^4.0.0-rc.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + checksum: 239d8c8db728183e570735f4bd42c92d65eace219a38a3e7d895680030daf0f4a66004e88b7c3d57575b42b0b39801d31dd60b8d0d127bf713e645433c847ea4 + languageName: node + linkType: hard + +"@yarnpkg/plugin-essentials@npm:^4.1.1": + version: 4.1.1 + resolution: "@yarnpkg/plugin-essentials@npm:4.1.1" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/parsers": ^3.0.0 + ci-info: ^3.2.0 + clipanion: ^4.0.0-rc.2 + enquirer: ^2.3.6 + lodash: ^4.17.15 + micromatch: ^4.0.2 + semver: ^7.1.2 + tslib: ^2.4.0 + typanion: ^3.14.0 + peerDependencies: + "@yarnpkg/cli": ^4.1.1 + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-git": ^3.0.0 + checksum: 0992309971e90f05b795b04396668b9949db7e532035f4ce395378e698b5145048f1386a451db1978f59f8523636000fde2defa342ff1b3c38457714151119d4 + languageName: node + linkType: hard + +"@yarnpkg/plugin-exec@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/plugin-exec@npm:3.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.0 + checksum: 66ae5c6b48607a0fa7095bcea4304c384628b537cf02440d2ccc35847aeaeac07d09b7b215870000c048d0ff421a30771c5c57592ae2276c3ca630f7fd57fb2a + languageName: node + linkType: hard + +"@yarnpkg/plugin-file@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/plugin-file@npm:3.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + "@yarnpkg/libzip": ^3.0.0 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.0 + checksum: 149e57f555666b77eaf8e4035629f28bfbb026d20dc97720b7b8ee01781639ac29db5e27212a6b4980dd67097da4baa6297786c964f1e0321137489cdcb1fd31 + languageName: node + linkType: hard + +"@yarnpkg/plugin-git@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/plugin-git@npm:3.0.0" + dependencies: + "@types/semver": ^7.1.0 + "@yarnpkg/fslib": ^3.0.0 + clipanion: ^4.0.0-rc.2 + git-url-parse: ^13.1.0 + lodash: ^4.17.15 + semver: ^7.1.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.0 + checksum: d75ed9d339905e81d5ffb8d0cac5aa2cf2e106d322c4dc64acac0e53a00e6c7cd5fd931d7373b1d944d11fd4f4685188e5f445fce34394a627be77eade39b769 + languageName: node + linkType: hard + +"@yarnpkg/plugin-github@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/plugin-github@npm:3.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.0 + "@yarnpkg/plugin-git": ^3.0.0 + checksum: a8aa25ac79dfb547960446ea00e1afa65f14c5032a926b250f20d8f21e1a8b212aab90e7ae2830655c2a2257b9f989a8222dbdabcbc46be16796fa36e7aa7abe + languageName: node + linkType: hard + +"@yarnpkg/plugin-http@npm:^3.0.1": + version: 3.0.1 + resolution: "@yarnpkg/plugin-http@npm:3.0.1" + dependencies: + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.2 + checksum: 928d22cf37ff90501fbbc48ddff162c63e254100fe5f01c46b979458514f14d892f577047e90ced997e4c938edbe4b65b6580f9f5c0390b6b28bce1f0b2f4804 + languageName: node + linkType: hard + +"@yarnpkg/plugin-init@npm:^4.0.1": + version: 4.0.1 + resolution: "@yarnpkg/plugin-init@npm:4.0.1" + dependencies: + "@yarnpkg/fslib": ^3.0.1 + clipanion: ^4.0.0-rc.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.2 + "@yarnpkg/core": ^4.0.2 + checksum: d419f4e021f74b249be87b768ce10256407872d3a2af92dc51e92f3b5f779f2447af45483d76641651bac6e474f5c3fd275e4764422848bfaeb19ce7e50d97f3 + languageName: node + linkType: hard + +"@yarnpkg/plugin-interactive-tools@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/plugin-interactive-tools@npm:4.0.0" + dependencies: + "@yarnpkg/libui": ^3.0.0 + algoliasearch: ^4.2.0 + clipanion: ^4.0.0-rc.2 + diff: ^5.1.0 + ink: ^3.0.8 + ink-text-input: ^4.0.1 + react: ^16.13.1 + semver: ^7.1.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + "@yarnpkg/plugin-essentials": ^4.0.0 + checksum: 43a50edf1e21582d0fd758077c787228e6145fa235e726bb4b8e2bdbcbd2ec0118ec63bc2ab6d3342ad2c06dc713bc871fa33bbb17de75d0c0c437daad2a666b + languageName: node + linkType: hard + +"@yarnpkg/plugin-link@npm:^3.0.0": + version: 3.0.0 + resolution: "@yarnpkg/plugin-link@npm:3.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.0 + checksum: 48bdb0e7ac8f9544999237d90f8b64163c1959d9e6f6a67d14799ef1c6533d5f30c7fa896129ed7b7ac693a9ce111646878ec4f505a39f5494df5db34cc372c4 + languageName: node + linkType: hard + +"@yarnpkg/plugin-nm@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/plugin-nm@npm:4.0.2" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/libzip": ^3.0.1 + "@yarnpkg/nm": ^4.0.2 + "@yarnpkg/parsers": ^3.0.0 + "@yarnpkg/plugin-pnp": ^4.0.2 + "@yarnpkg/pnp": ^4.0.2 + "@zkochan/cmd-shim": ^5.1.0 + clipanion: ^4.0.0-rc.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.1.0 + "@yarnpkg/core": ^4.0.3 + checksum: d7fad715a126dee644d3cb9a64fb6aac6ac1e179f08d72853b5247460a1033d81e7070f35bff196b16b0e0816c7a4e1e211f9a596c5af07ff6f84fff4a23cd61 + languageName: node + linkType: hard + +"@yarnpkg/plugin-npm-cli@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/plugin-npm-cli@npm:4.0.2" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + clipanion: ^4.0.0-rc.2 + enquirer: ^2.3.6 + micromatch: ^4.0.2 + semver: ^7.1.2 + tslib: ^2.4.0 + typanion: ^3.14.0 + peerDependencies: + "@yarnpkg/cli": ^4.1.0 + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-npm": ^3.0.1 + "@yarnpkg/plugin-pack": ^4.0.0 + checksum: af338409d242045830276e78740b011afefb0950699cfb04b895b6962c9ba6a2a11e72eddbc04b3a568d5b0cb153ae68e22bbecfd34eedd5559681c18ac7e0c0 + languageName: node + linkType: hard + +"@yarnpkg/plugin-npm@npm:^3.0.1": + version: 3.0.1 + resolution: "@yarnpkg/plugin-npm@npm:3.0.1" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + enquirer: ^2.3.6 + lodash: ^4.17.15 + semver: ^7.1.2 + ssri: ^6.0.1 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-pack": ^4.0.0 + checksum: 5b415fe84dfc306731c858c99523515766fcfbf75eb8fe17e2d0d2bd4fde525004df6477d71b418f4cc46f711b557feba4854d6216d49a2d1436ff4096c96dac + languageName: node + linkType: hard + +"@yarnpkg/plugin-pack@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/plugin-pack@npm:4.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + clipanion: ^4.0.0-rc.2 + micromatch: ^4.0.2 + tar-stream: ^2.0.1 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + checksum: 566cd532e83f135d5d4848ed7d392c9136dda1bc38470bf26cbfdf615ed0a3410e9c01373ae42ce747c906734f02b25c75df636f425974a3394232c730f9e250 + languageName: node + linkType: hard + +"@yarnpkg/plugin-patch@npm:^4.0.1": + version: 4.0.1 + resolution: "@yarnpkg/plugin-patch@npm:4.0.1" + dependencies: + "@yarnpkg/fslib": ^3.0.1 + "@yarnpkg/libzip": ^3.0.0 + clipanion: ^4.0.0-rc.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.2 + "@yarnpkg/core": ^4.0.2 + checksum: c534b80facd573ddc6888d7a9b739a309295a600c105415ce6caf9b7ab5f2ca6983ba932fb35acca7de7d17e58fc4396cf28d051624007c97decc3c10c389d57 + languageName: node + linkType: hard + +"@yarnpkg/plugin-pnp@npm:^4.0.0, @yarnpkg/plugin-pnp@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/plugin-pnp@npm:4.0.2" + dependencies: + "@yarnpkg/fslib": ^3.0.1 + "@yarnpkg/plugin-stage": ^4.0.0 + "@yarnpkg/pnp": ^4.0.1 + clipanion: ^4.0.0-rc.2 + micromatch: ^4.0.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.2 + "@yarnpkg/core": ^4.0.2 + checksum: 29656bef3ee4c151172f64475a782efde77df3df996c397c34aa633deb9f9e3b562c18c6ed32b8555598adde062b6cd598bc630c28f4648498abf84652a76d6b + languageName: node + linkType: hard + +"@yarnpkg/plugin-pnpm@npm:^2.0.0": + version: 2.0.0 + resolution: "@yarnpkg/plugin-pnpm@npm:2.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + "@yarnpkg/plugin-pnp": ^4.0.0 + "@yarnpkg/plugin-stage": ^4.0.0 + clipanion: ^4.0.0-rc.2 + p-limit: ^2.2.0 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + checksum: 5ec39a8f431eda3a8877e286a9ab88c719b3451d1a5009acaaf2370321288d40d8dc34495162eb89573aa8e00bddc6b6563bebfce459f9efe24589cbe5f9d4e9 + languageName: node + linkType: hard + +"@yarnpkg/plugin-stage@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/plugin-stage@npm:4.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + clipanion: ^4.0.0-rc.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + checksum: b315ef24433151161cc931bf3ad72db08f7a2a611ee4a83da1fa96278384aee6d62c250314bcaabd41d0522b328ad4094a13bcf73d14babb6b03cc2ea7656761 + languageName: node + linkType: hard + +"@yarnpkg/plugin-typescript@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/plugin-typescript@npm:4.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + "@yarnpkg/plugin-pack": ^4.0.0 + algoliasearch: ^4.2.0 + semver: ^7.1.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.0.0 + "@yarnpkg/core": ^4.0.0 + "@yarnpkg/plugin-essentials": ^4.0.0 + checksum: 7ce40990039149acd8e62c6e150f0201638beb13cc78675a734b9024db22a6d6914dce090e805dc476795972897a849c154aa0371262dd8dec9743ac2df53944 + languageName: node + linkType: hard + +"@yarnpkg/plugin-version@npm:^4.0.1": + version: 4.0.1 + resolution: "@yarnpkg/plugin-version@npm:4.0.1" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + "@yarnpkg/libui": ^3.0.0 + "@yarnpkg/parsers": ^3.0.0 + clipanion: ^4.0.0-rc.2 + ink: ^3.0.8 + lodash: ^4.17.15 + react: ^16.13.1 + semver: ^7.1.2 + tslib: ^2.4.0 + peerDependencies: + "@yarnpkg/cli": ^4.1.0 + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-git": ^3.0.0 + checksum: d155f675f2298f50c34f864d1598a9de8a10d6168909aa77904941f08212d3d23de0cfb5e6ca80f8ab738a3f5593a0d8046f1f5f7e8c6b3f3d4b2541b6e5625b + languageName: node + linkType: hard + +"@yarnpkg/plugin-workspace-tools@npm:^4.1.0": + version: 4.1.0 + resolution: "@yarnpkg/plugin-workspace-tools@npm:4.1.0" + dependencies: + "@yarnpkg/fslib": ^3.0.2 + clipanion: ^4.0.0-rc.2 + micromatch: ^4.0.2 + p-limit: ^2.2.0 + tslib: ^2.4.0 + typanion: ^3.14.0 + peerDependencies: + "@yarnpkg/cli": ^4.1.0 + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/plugin-git": ^3.0.0 + checksum: 8ee82796e1f86267827bf9fd25b07e63914732817fdcf8debe9d60e8e1ead87f79c8fb7b9bc60a78e097a1920579fb044b8f37aa28a3b5e7902893fc7e712957 + languageName: node + linkType: hard + +"@yarnpkg/pnp@npm:^4.0.1, @yarnpkg/pnp@npm:^4.0.2": + version: 4.0.2 + resolution: "@yarnpkg/pnp@npm:4.0.2" + dependencies: + "@types/node": ^18.17.15 + "@yarnpkg/fslib": ^3.0.2 + checksum: 7efd3702e83495b22452f79e56fc753f71e9f57613acaa775f64ec026b585cc8d3d6e2be6afeed9f6fbaa6034814eb25b70bc8a451c1f860100143d6e0e59c75 + languageName: node + linkType: hard + +"@yarnpkg/shell@npm:^4.0.0": + version: 4.0.0 + resolution: "@yarnpkg/shell@npm:4.0.0" + dependencies: + "@yarnpkg/fslib": ^3.0.0 + "@yarnpkg/parsers": ^3.0.0 + chalk: ^3.0.0 + clipanion: ^4.0.0-rc.2 + cross-spawn: 7.0.3 + fast-glob: ^3.2.2 + micromatch: ^4.0.2 + tslib: ^2.4.0 + bin: + shell: ./lib/cli.js + checksum: 8497e278b1d3d0ffe324a3b9c878ca7165bbbe4d182f5ecb02f1bfaaf4dd18c8aaa54c33ee17bb37eb09173816dc4617b70c3fe0925f5fb99749687e2650b7a2 + languageName: node + linkType: hard + +"@zkochan/cmd-shim@npm:^5.1.0": + version: 5.4.1 + resolution: "@zkochan/cmd-shim@npm:5.4.1" + dependencies: + cmd-extension: ^1.0.2 + graceful-fs: ^4.2.10 + is-windows: ^1.0.2 + checksum: 418b4b3a5fb36960f9a96adb6ba3946be0494ab06be1959c8b2805fe37f7ebca9d185108138e30c7ff193eac74eebd10a361eca949a608c9e16afbffd6a48482 + languageName: node + linkType: hard + "@zkochan/retry@npm:^0.2.0": version: 0.2.0 resolution: "@zkochan/retry@npm:0.2.0" @@ -19615,6 +20353,29 @@ __metadata: languageName: node linkType: hard +"algoliasearch@npm:^4.2.0": + version: 4.23.2 + resolution: "algoliasearch@npm:4.23.2" + dependencies: + "@algolia/cache-browser-local-storage": 4.23.2 + "@algolia/cache-common": 4.23.2 + "@algolia/cache-in-memory": 4.23.2 + "@algolia/client-account": 4.23.2 + "@algolia/client-analytics": 4.23.2 + "@algolia/client-common": 4.23.2 + "@algolia/client-personalization": 4.23.2 + "@algolia/client-search": 4.23.2 + "@algolia/logger-common": 4.23.2 + "@algolia/logger-console": 4.23.2 + "@algolia/recommend": 4.23.2 + "@algolia/requester-browser-xhr": 4.23.2 + "@algolia/requester-common": 4.23.2 + "@algolia/requester-node-http": 4.23.2 + "@algolia/transporter": 4.23.2 + checksum: 25a3303a5aff34a049c9d115d140650b4178b4cf2d78b23f4e8bdae7caa5e1a61d22c888a12d162ac22cfeba99e2579b4c17b03ccd33f5b5446c9db8f10ff712 + languageName: node + linkType: hard + "alphanum-sort@npm:^1.0.2": version: 1.0.2 resolution: "alphanum-sort@npm:1.0.2" @@ -20273,6 +21034,13 @@ __metadata: languageName: node linkType: hard +"auto-bind@npm:4.0.0": + version: 4.0.0 + resolution: "auto-bind@npm:4.0.0" + checksum: 00cad71cce5742faccb7dd65c1b55ebc4f45add4b0c9a1547b10b05bab22813230133b0c892c67ba3eb969a4524710c5e43cc45c72898ec84e56f3a596e7a04f + languageName: node + linkType: hard + "autolinker@npm:^3.11.0": version: 3.16.2 resolution: "autolinker@npm:3.16.2" @@ -21753,7 +22521,7 @@ __metadata: languageName: node linkType: hard -"cli-boxes@npm:^2.2.1": +"cli-boxes@npm:^2.2.0, cli-boxes@npm:^2.2.1": version: 2.2.1 resolution: "cli-boxes@npm:2.2.1" checksum: be79f8ec23a558b49e01311b39a1ea01243ecee30539c880cf14bf518a12e223ef40c57ead0cb44f509bffdffc5c129c746cd50d863ab879385370112af4f585 @@ -21819,6 +22587,16 @@ __metadata: languageName: node linkType: hard +"cli-truncate@npm:^2.1.0": + version: 2.1.0 + resolution: "cli-truncate@npm:2.1.0" + dependencies: + slice-ansi: ^3.0.0 + string-width: ^4.2.0 + checksum: bf1e4e6195392dc718bf9cd71f317b6300dc4a9191d052f31046b8773230ece4fa09458813bf0e3455a5e68c0690d2ea2c197d14a8b85a7b5e01c97f4b5feb5d + languageName: node + linkType: hard + "cli-truncate@npm:^4.0.0": version: 4.0.0 resolution: "cli-truncate@npm:4.0.0" @@ -21850,6 +22628,17 @@ __metadata: languageName: node linkType: hard +"clipanion@npm:^4.0.0-rc.2": + version: 4.0.0-rc.3 + resolution: "clipanion@npm:4.0.0-rc.3" + dependencies: + typanion: ^3.8.0 + peerDependencies: + typanion: "*" + checksum: a5e6201e5a7fdb93dbe5f61d158d3e3d23e3164c38a7c679c7dcc599e10ee339d249c33fd8729ba8ffd0a376206ed14aac2e5472624ecaf79041fac3baa73b9b + languageName: node + linkType: hard + "cliui@npm:7.0.4, cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -21963,6 +22752,13 @@ __metadata: languageName: node linkType: hard +"cmd-extension@npm:^1.0.2": + version: 1.0.2 + resolution: "cmd-extension@npm:1.0.2" + checksum: 4cbcdd53196a3c1db3484f67aa49ed83c0e6069713f60193a94d747cb84050e8e64d688673aa5159cf0184e054cb806ceb6119e45744f721cbd3a09a3e7038cb + languageName: node + linkType: hard + "cmd-shim@npm:^4.0.1": version: 4.1.0 resolution: "cmd-shim@npm:4.1.0" @@ -21986,6 +22782,15 @@ __metadata: languageName: node linkType: hard +"code-excerpt@npm:^3.0.0": + version: 3.0.0 + resolution: "code-excerpt@npm:3.0.0" + dependencies: + convert-to-spaces: ^1.0.1 + checksum: fa3a8ed15967076a43a4093b0c824cf0ada15d9aab12ea3c028851b72a69b56495aac1eadf18c3b6ae4baf0a95bb1e1faa9dbeeb0a2b2b5ae058da23328e9dd8 + languageName: node + linkType: hard + "codemirror-graphql@npm:^2.0.10": version: 2.0.11 resolution: "codemirror-graphql@npm:2.0.11" @@ -22191,6 +22996,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:7.2.0, commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc + languageName: node + linkType: hard + "commander@npm:8.3.0, commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" @@ -22233,13 +23045,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^7.2.0": - version: 7.2.0 - resolution: "commander@npm:7.2.0" - checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc - languageName: node - linkType: hard - "common-ancestor-path@npm:^1.0.1": version: 1.0.1 resolution: "common-ancestor-path@npm:1.0.1" @@ -22562,6 +23367,13 @@ __metadata: languageName: node linkType: hard +"convert-to-spaces@npm:^1.0.1": + version: 1.0.2 + resolution: "convert-to-spaces@npm:1.0.2" + checksum: e73f2ae39eb2b184f0796138eaab9c088b03b94937377d31be5b2282aef6a6ccce6b46f51bd99b3b7dfc70f516e2a6b16c0dd911883bfadf8d1073f462480224 + languageName: node + linkType: hard + "cookie-parser@npm:^1.4.5, cookie-parser@npm:^1.4.6": version: 1.4.6 resolution: "cookie-parser@npm:1.4.6" @@ -22896,6 +23708,17 @@ __metadata: languageName: node linkType: hard +"cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 + languageName: node + linkType: hard + "cross-spawn@npm:^5.1.0": version: 5.1.0 resolution: "cross-spawn@npm:5.1.0" @@ -22920,17 +23743,6 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.1, cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.3": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: ^3.1.0 - shebang-command: ^2.0.0 - which: ^2.0.1 - checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52 - languageName: node - linkType: hard - "crosspath@npm:^2.0.0": version: 2.0.0 resolution: "crosspath@npm:2.0.0" @@ -24254,10 +25066,10 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.0.0, dotenv@npm:^16.0.3": - version: 16.3.1 - resolution: "dotenv@npm:16.3.1" - checksum: 15d75e7279018f4bafd0ee9706593dd14455ddb71b3bcba9c52574460b7ccaf67d5cf8b2c08a5af1a9da6db36c956a04a1192b101ee102a3e0cf8817bbcf3dfd +"dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.1": + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 301a12c3d44fd49888b74eb9ccf9f07a1f5df43f489e7fcb89647a2edcd84c42d6bc349dc8df099cd18f07c35c7b04685c1a4f3e6a6a9e6b30f8d48c15b7f49c languageName: node linkType: hard @@ -24549,12 +25361,13 @@ __metadata: languageName: node linkType: hard -"enquirer@npm:^2.3.0": - version: 2.3.6 - resolution: "enquirer@npm:2.3.6" +"enquirer@npm:^2.3.0, enquirer@npm:^2.3.6": + version: 2.4.1 + resolution: "enquirer@npm:2.4.1" dependencies: ansi-colors: ^4.1.1 - checksum: 1c0911e14a6f8d26721c91e01db06092a5f7675159f0261d69c403396a385afd13dd76825e7678f66daffa930cfaa8d45f506fb35f818a2788463d022af1b884 + strip-ansi: ^6.0.1 + checksum: f080f11a74209647dbf347a7c6a83c8a47ae1ebf1e75073a808bc1088eb780aa54075bfecd1bcdb3e3c724520edb8e6ee05da031529436b421b71066fcc48cb5 languageName: node linkType: hard @@ -25009,6 +25822,15 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:esbuild-wasm@^0.15.15": + version: 0.15.18 + resolution: "esbuild-wasm@npm:0.15.18" + bin: + esbuild: bin/esbuild + checksum: 8e809acd497ee2170f0bb6bd7296d0b04f5ddfa79fb4ee1fb8431523822805a07b4a4e671efa06af6d4f078a876b10c7504f8d170808c8033c8a086f3075cb61 + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -26110,7 +26932,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.3.2, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": +"fast-glob@npm:3.3.2, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.2": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -26317,6 +27139,13 @@ __metadata: languageName: node linkType: hard +"figgy-pudding@npm:^3.5.1": + version: 3.5.2 + resolution: "figgy-pudding@npm:3.5.2" + checksum: 4090bd66193693dcda605e44d6b8715d8fb5c92a67acd57826e55cf816a342f550d57e5638f822b39366e1b2fdb244e99b3068a37213aa1d6c1bf602b8fde5ae + languageName: node + linkType: hard + "figures@npm:^3.0.0, figures@npm:^3.2.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -27369,6 +28198,13 @@ __metadata: languageName: node linkType: hard +"globalyzer@npm:0.1.0": + version: 0.1.0 + resolution: "globalyzer@npm:0.1.0" + checksum: 419a0f95ba542534fac0842964d31b3dc2936a479b2b1a8a62bad7e8b61054faa9b0a06ad9f2e12593396b9b2621cac93358d9b3071d33723fb1778608d358a1 + languageName: node + linkType: hard + "globby@npm:^11.0.0, globby@npm:^11.0.1, globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" @@ -27396,6 +28232,13 @@ __metadata: languageName: node linkType: hard +"globrex@npm:^0.1.2": + version: 0.1.2 + resolution: "globrex@npm:0.1.2" + checksum: adca162494a176ce9ecf4dd232f7b802956bb1966b37f60c15e49d2e7d961b66c60826366dc2649093cad5a0d69970cfa8875bd1695b5a1a2f33dcd2aa88da3c + languageName: node + linkType: hard + "goober@npm:^2.0.33": version: 2.1.14 resolution: "goober@npm:2.1.14" @@ -27454,9 +28297,9 @@ __metadata: languageName: node linkType: hard -"got@npm:^11.8.3": - version: 11.8.5 - resolution: "got@npm:11.8.5" +"got@npm:^11.7.0, got@npm:^11.8.3": + version: 11.8.6 + resolution: "got@npm:11.8.6" dependencies: "@sindresorhus/is": ^4.0.0 "@szmarczak/http-timer": ^4.0.5 @@ -27469,7 +28312,7 @@ __metadata: lowercase-keys: ^2.0.0 p-cancelable: ^2.0.0 responselike: ^2.0.0 - checksum: 2de8a1bbda4e9b6b2b72b2d2100bc055a59adc1740529e631f61feb44a8b9a1f9f8590941ed9da9df0090b6d6d0ed8ffee94cd9ac086ec3409b392b33440f7d2 + checksum: bbc783578a8d5030c8164ef7f57ce41b5ad7db2ed13371e1944bef157eeca5a7475530e07c0aaa71610d7085474d0d96222c9f4268d41db333a17e39b463f45d languageName: node linkType: hard @@ -28602,6 +29445,56 @@ __metadata: languageName: node linkType: hard +"ink-text-input@npm:^4.0.1": + version: 4.0.3 + resolution: "ink-text-input@npm:4.0.3" + dependencies: + chalk: ^4.1.0 + type-fest: ^0.15.1 + peerDependencies: + ink: ^3.0.0-3 + react: ^16.5.2 || ^17.0.0 + checksum: 2d309ec8ca386010d467822e317389e3c60b764fd04091df063a45c31f43104fd9f4a4e71a928a2c3c3cca461a9b8a526e90439616760f0f3726507132abbac5 + languageName: node + linkType: hard + +"ink@npm:^3.0.8": + version: 3.2.0 + resolution: "ink@npm:3.2.0" + dependencies: + ansi-escapes: ^4.2.1 + auto-bind: 4.0.0 + chalk: ^4.1.0 + cli-boxes: ^2.2.0 + cli-cursor: ^3.1.0 + cli-truncate: ^2.1.0 + code-excerpt: ^3.0.0 + indent-string: ^4.0.0 + is-ci: ^2.0.0 + lodash: ^4.17.20 + patch-console: ^1.0.0 + react-devtools-core: ^4.19.1 + react-reconciler: ^0.26.2 + scheduler: ^0.20.2 + signal-exit: ^3.0.2 + slice-ansi: ^3.0.0 + stack-utils: ^2.0.2 + string-width: ^4.2.2 + type-fest: ^0.12.0 + widest-line: ^3.1.0 + wrap-ansi: ^6.2.0 + ws: ^7.5.5 + yoga-layout-prebuilt: ^1.9.6 + peerDependencies: + "@types/react": ">=16.8.0" + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 35f1b733b94bf12cc0bf7acb4d3fcba9d961ede15cee9c64a7325606b74cee78e1009eaffbac127f4d7d28e758d8259dea8d0850bfacb991b8d93632f41d3fa2 + languageName: node + linkType: hard + "inline-style-parser@npm:0.1.1": version: 0.1.1 resolution: "inline-style-parser@npm:0.1.1" @@ -29449,7 +30342,7 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.0": +"is-windows@npm:^1.0.0, is-windows@npm:^1.0.2": version: 1.0.2 resolution: "is-windows@npm:1.0.2" checksum: 438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 @@ -34055,6 +34948,13 @@ __metadata: languageName: node linkType: hard +"node-watch@npm:0.7.3": + version: 0.7.3 + resolution: "node-watch@npm:0.7.3" + checksum: c745482f720613415153b9065383b77d21f2ef60ceabf64f779c1452b1dcbb8d08c71f650b93f3c1d84524371321f92a15fda468745872cacffec8289741d51a + languageName: node + linkType: hard + "nodemailer@npm:^6.9.13": version: 6.9.13 resolution: "nodemailer@npm:6.9.13" @@ -35392,6 +36292,13 @@ __metadata: languageName: node linkType: hard +"patch-console@npm:^1.0.0": + version: 1.0.0 + resolution: "patch-console@npm:1.0.0" + checksum: 8cd738aa470f2e9463fca35da6a19403384ac555004f698ddd3dfdb69135ab60fe9bd2edd1dbdd8c09d92c0a2190fd0f7337fe48123013baf8ffec8532885a3a + languageName: node + linkType: hard + "patch-package@npm:^8.0.0": version: 8.0.0 resolution: "patch-package@npm:8.0.0" @@ -37039,6 +37946,19 @@ __metadata: languageName: node linkType: hard +"qunit@npm:^2.8.0": + version: 2.20.1 + resolution: "qunit@npm:2.20.1" + dependencies: + commander: 7.2.0 + node-watch: 0.7.3 + tiny-glob: 0.2.9 + bin: + qunit: bin/qunit.js + checksum: ee0db04239ff7ae1ff9b67f15ab31e8c4f1e41bb5d6a41f34b19b17f836bc9414e43897516a617d08840eaa2bd71580c456e7e448d81c388dfb58198f0c26de7 + languageName: node + linkType: hard + "raf-schd@npm:^4.0.2": version: 4.0.2 resolution: "raf-schd@npm:4.0.2" @@ -37283,6 +38203,16 @@ __metadata: languageName: node linkType: hard +"react-devtools-core@npm:^4.19.1": + version: 4.28.5 + resolution: "react-devtools-core@npm:4.28.5" + dependencies: + shell-quote: ^1.6.1 + ws: ^7 + checksum: d8e4b32ffcfe1ada5c9f7decffd04afc4707a3d6261953a92b8aed1c8abe15cd57d6eb4ce711f842180a2f5c60d2947209e3c1202f7ea29303ee150c55da59e0 + languageName: node + linkType: hard + "react-dom@npm:^16.13.1": version: 16.14.0 resolution: "react-dom@npm:16.14.0" @@ -37515,6 +38445,19 @@ __metadata: languageName: node linkType: hard +"react-reconciler@npm:^0.26.2": + version: 0.26.2 + resolution: "react-reconciler@npm:0.26.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + scheduler: ^0.20.2 + peerDependencies: + react: ^17.0.2 + checksum: 2ebceace56f547f51eaf142becefef9cca980eae4f42d90ee5a966f54a375f5082d78b71b00c40bbd9bca69e0e0f698c7d4e81cc7373437caa19831fddc1d01b + languageName: node + linkType: hard + "react-redux@npm:^7.1.1": version: 7.2.5 resolution: "react-redux@npm:7.2.5" @@ -37860,6 +38803,17 @@ __metadata: languageName: node linkType: hard +"react@npm:^16.13.1": + version: 16.14.0 + resolution: "react@npm:16.14.0" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + prop-types: ^15.6.2 + checksum: 8484f3ecb13414526f2a7412190575fc134da785c02695eb92bb6028c930bfe1c238d7be2a125088fec663cc7cda0a3623373c46807cf2c281f49c34b79881ac + languageName: node + linkType: hard + "react@npm:^18.0.2": version: 18.2.0 resolution: "react@npm:18.2.0" @@ -38018,6 +38972,13 @@ __metadata: languageName: node linkType: hard +"readline-sync@npm:1.4.9": + version: 1.4.9 + resolution: "readline-sync@npm:1.4.9" + checksum: cedd48f422bb4c8736cbd44332bea9d3367302d0e2a63c064b97e909bbcd203099d483cee4fff4e78614a1c3c1d5a62f1c63bf2c013483072ec1ff1c8a2c5129 + languageName: node + linkType: hard + "recast@npm:^0.20.3": version: 0.20.4 resolution: "recast@npm:0.20.4" @@ -39160,6 +40121,16 @@ __metadata: languageName: node linkType: hard +"scheduler@npm:^0.20.2": + version: 0.20.2 + resolution: "scheduler@npm:0.20.2" + dependencies: + loose-envify: ^1.1.0 + object-assign: ^4.1.1 + checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + languageName: node + linkType: hard + "scheduler@npm:^0.23.0": version: 0.23.0 resolution: "scheduler@npm:0.23.0" @@ -39302,7 +40273,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.4.0, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": +"semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.4.0, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": version: 7.6.0 resolution: "semver@npm:7.6.0" dependencies: @@ -39555,7 +40526,7 @@ __metadata: languageName: node linkType: hard -"shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": +"shell-quote@npm:^1.6.1, shell-quote@npm:^1.7.3, shell-quote@npm:^1.8.1": version: 1.8.1 resolution: "shell-quote@npm:1.8.1" checksum: 5f01201f4ef504d4c6a9d0d283fa17075f6770bfbe4c5850b074974c68062f37929ca61700d95ad2ac8822e14e8c4b990ca0e6e9272e64befd74ce5e19f0736b @@ -39728,6 +40699,17 @@ __metadata: languageName: node linkType: hard +"slice-ansi@npm:^3.0.0": + version: 3.0.0 + resolution: "slice-ansi@npm:3.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 5ec6d022d12e016347e9e3e98a7eb2a592213a43a65f1b61b74d2c78288da0aded781f665807a9f3876b9daa9ad94f64f77d7633a0458876c3a4fdc4eb223f24 + languageName: node + linkType: hard + "slice-ansi@npm:^4.0.0": version: 4.0.0 resolution: "slice-ansi@npm:4.0.0" @@ -40181,6 +41163,15 @@ __metadata: languageName: node linkType: hard +"ssri@npm:^6.0.1": + version: 6.0.2 + resolution: "ssri@npm:6.0.2" + dependencies: + figgy-pudding: ^3.5.1 + checksum: 7c2e5d442f6252559c8987b7114bcf389fe5614bf65de09ba3e6f9a57b9b65b2967de348fcc3acccff9c069adb168140dd2c5fc2f6f4a779e604a27ef1f7d551 + languageName: node + linkType: hard + "ssri@npm:^8.0.0, ssri@npm:^8.0.1": version: 8.0.1 resolution: "ssri@npm:8.0.1" @@ -40222,12 +41213,12 @@ __metadata: languageName: node linkType: hard -"stack-utils@npm:^2.0.3": - version: 2.0.5 - resolution: "stack-utils@npm:2.0.5" +"stack-utils@npm:^2.0.2, stack-utils@npm:^2.0.3": + version: 2.0.6 + resolution: "stack-utils@npm:2.0.6" dependencies: escape-string-regexp: ^2.0.0 - checksum: 76b69da0f5b48a34a0f93c98ee2a96544d2c4ca2557f7eef5ddb961d3bdc33870b46f498a84a7c4f4ffb781df639840e7ebf6639164ed4da5e1aeb659615b9c7 + checksum: 052bf4d25bbf5f78e06c1d5e67de2e088b06871fa04107ca8d3f0e9d9263326e2942c8bedee3545795fc77d787d443a538345eef74db2f8e35db3558c6f91ff7 languageName: node linkType: hard @@ -41101,7 +42092,7 @@ __metadata: languageName: node linkType: hard -"tar-stream@npm:^2.0.0, tar-stream@npm:^2.1.4, tar-stream@npm:^2.2.0": +"tar-stream@npm:^2.0.0, tar-stream@npm:^2.0.1, tar-stream@npm:^2.1.4, tar-stream@npm:^2.2.0": version: 2.2.0 resolution: "tar-stream@npm:2.2.0" dependencies: @@ -41125,7 +42116,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.2, tar@npm:^6.1.0, tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.2": +"tar@npm:^6.0.2, tar@npm:^6.0.5, tar@npm:^6.1.0, tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.2": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -41146,6 +42137,16 @@ __metadata: languageName: node linkType: hard +"tau-prolog@npm:^0.2.66": + version: 0.2.81 + resolution: "tau-prolog@npm:0.2.81" + dependencies: + qunit: ^2.8.0 + readline-sync: 1.4.9 + checksum: 9771c020fe37e821f9e5321ef26f70728f885077c5885d4e8b06fd9409205b1d0ad9fd9ac02d66e56e062ce8e8bbc07a9bf8c3791b5023bfe72ed04c598dd3ef + languageName: node + linkType: hard + "tdigest@npm:^0.1.1": version: 0.1.1 resolution: "tdigest@npm:0.1.1" @@ -41410,6 +42411,16 @@ __metadata: languageName: node linkType: hard +"tiny-glob@npm:0.2.9": + version: 0.2.9 + resolution: "tiny-glob@npm:0.2.9" + dependencies: + globalyzer: 0.1.0 + globrex: ^0.1.2 + checksum: aea5801eb6663ddf77ebb74900b8f8bd9dfcfc9b6a1cc8018cb7421590c00bf446109ff45e4b64a98e6c95ddb1255a337a5d488fb6311930e2a95334151ec9c6 + languageName: node + linkType: hard + "tiny-invariant@npm:^1.0.6": version: 1.3.1 resolution: "tiny-invariant@npm:1.3.1" @@ -41424,6 +42435,13 @@ __metadata: languageName: node linkType: hard +"tinylogic@npm:^2.0.0": + version: 2.0.0 + resolution: "tinylogic@npm:2.0.0" + checksum: b966cbb41241a048095fb9e685d5e2020475fdea2c65b4ae51e5dee48964860a4505d987503c004b8a76e96b64c7da2f49954dd36c691d559c315d878ce7da29 + languageName: node + linkType: hard + "tmp@npm:^0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -41647,6 +42665,13 @@ __metadata: languageName: node linkType: hard +"treeify@npm:^1.1.0": + version: 1.1.0 + resolution: "treeify@npm:1.1.0" + checksum: aa00dded220c1dd052573bd6fc2c52862f09870851a284f0d3650d72bf913ba9b4f6b824f4f1ab81899bae29375f4266b07fe47cbf82343a1efa13cc09ce87af + languageName: node + linkType: hard + "treeverse@npm:^1.0.4": version: 1.0.4 resolution: "treeverse@npm:1.0.4" @@ -41888,6 +42913,13 @@ __metadata: languageName: node linkType: hard +"typanion@npm:^3.14.0, typanion@npm:^3.8.0": + version: 3.14.0 + resolution: "typanion@npm:3.14.0" + checksum: fc0590d02c13c659eb1689e8adf7777e6c00dc911377e44cd36fe1b1271cfaca71547149f12cdc275058c0de5562a14e5273adbae66d47e6e0320e36007f5912 + languageName: node + linkType: hard + "type-check@npm:^0.4.0, type-check@npm:~0.4.0": version: 0.4.0 resolution: "type-check@npm:0.4.0" @@ -41913,6 +42945,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.12.0": + version: 0.12.0 + resolution: "type-fest@npm:0.12.0" + checksum: 407d6c1a6fcc907f6124c37e977ba4966205014787a32a27579da6e47c3b1bd210b68cc1c7764d904c8aa55fb4efa6945586f9b4fae742c63ed026a4559da07d + languageName: node + linkType: hard + "type-fest@npm:^0.13.1": version: 0.13.1 resolution: "type-fest@npm:0.13.1" @@ -41920,6 +42959,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.15.1": + version: 0.15.1 + resolution: "type-fest@npm:0.15.1" + checksum: a1a0cdbd7f802d9784324f185df055739e97424ecb60914e9025574a4bc07e4a063c152e4510ebf5989de8a263220de1f6b5cf1b05f0b333dbd5b21d9b4a271b + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -43778,7 +44824,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.4.6": +"ws@npm:^7, ws@npm:^7.4.6, ws@npm:^7.5.5": version: 7.5.9 resolution: "ws@npm:7.5.9" peerDependencies: @@ -44081,6 +45127,19 @@ __metadata: languageName: node linkType: hard +"yarn-plugin-backstage@workspace:packages/yarn-plugin": + version: 0.0.0-use.local + resolution: "yarn-plugin-backstage@workspace:packages/yarn-plugin" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/release-manifests": "workspace:^" + "@yarnpkg/builder": ^4.0.0 + "@yarnpkg/core": ^4.0.3 + "@yarnpkg/fslib": ^3.0.2 + nodemon: ^3.0.1 + languageName: unknown + linkType: soft + "yauzl@npm:^3.0.0": version: 3.1.3 resolution: "yauzl@npm:3.1.3" @@ -44169,6 +45228,15 @@ __metadata: languageName: node linkType: hard +"yoga-layout-prebuilt@npm:^1.9.6": + version: 1.10.0 + resolution: "yoga-layout-prebuilt@npm:1.10.0" + dependencies: + "@types/yoga-layout": 1.9.2 + checksum: 6954c7c7b04c585a1c974391bea4734611adb85702b5e9131549a1d3dc5b94e69bcfea34121cdaeb5e702663bf290fcce5374910128e54d1031503a57c062865 + languageName: node + linkType: hard + "yup@npm:*, yup@npm:^1.0.0": version: 1.4.0 resolution: "yup@npm:1.4.0" From 5eb9dfa82b50b85aec0a8357f749ec21824854da Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 9 Apr 2024 23:02:25 +0100 Subject: [PATCH 02/13] build(deps): manually restore previous version of @types/node Looks like we were getting caught by the below issue, or something related to it. Trying a revert of the change in resolved version of @types/node that came along with the new dependencies in packages/yarn-plugin. https://github.com/vitejs/vite/issues/15714 Signed-off-by: MT Lewis --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8b8caa5875..199462391b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17983,11 +17983,11 @@ __metadata: linkType: hard "@types/node@npm:^18.17.15, @types/node@npm:^18.17.8": - version: 18.19.31 - resolution: "@types/node@npm:18.19.31" + version: 18.19.8 + resolution: "@types/node@npm:18.19.8" dependencies: undici-types: ~5.26.4 - checksum: 949bddfd7071bd47300d1f33d380ee34695ccd5f046f1a03e4d2be0d953ace896905144d44a6f483f241b5ef34b86f0e40a0e312201117782eecf89e81a4ff13 + checksum: fa291495d6157a9d9393b4c3bdbf1ce12a8f661dc9da6a4fa19bcdb19af1c62bb8dbf7fb66ae135f29cd788b618e9845b83e9c47edcf39f0953a8561fdacd9a3 languageName: node linkType: hard From 197a51625c296e0b6ce17f8c8fc575b3f5406d71 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 9 Apr 2024 23:21:49 +0100 Subject: [PATCH 03/13] yarn-plugin: api report Signed-off-by: MT Lewis --- packages/yarn-plugin/api-report.md | 11 +++++++++++ packages/yarn-plugin/src/index.ts | 11 +++++++++++ .../yarn-plugin/src/resolver/BackstageResolver.ts | 1 + 3 files changed, 23 insertions(+) create mode 100644 packages/yarn-plugin/api-report.md diff --git a/packages/yarn-plugin/api-report.md b/packages/yarn-plugin/api-report.md new file mode 100644 index 0000000000..f0300ec9a1 --- /dev/null +++ b/packages/yarn-plugin/api-report.md @@ -0,0 +1,11 @@ +## API Report File for "yarn-plugin-backstage" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { Plugin as Plugin_2 } from '@yarnpkg/core'; + +// @public (undocumented) +const plugin: Plugin_2; +export default plugin; +``` diff --git a/packages/yarn-plugin/src/index.ts b/packages/yarn-plugin/src/index.ts index ce12c836dd..aac855fadf 100644 --- a/packages/yarn-plugin/src/index.ts +++ b/packages/yarn-plugin/src/index.ts @@ -13,9 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** + * Yarn plugin for resolving package versions based on + * a Backstage version manifest. + * + * @packageDocumentation + */ + import { Plugin } from '@yarnpkg/core'; import { BackstageResolver } from './resolver/BackstageResolver'; +/** + * @public + */ const plugin: Plugin = { resolvers: [BackstageResolver], }; diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index 5c227d84e4..8a28c481ed 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { structUtils, Descriptor, From 612d471d291afd46f224c9574ae074ba955b9ff6 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Wed, 10 Apr 2024 12:08:28 +0100 Subject: [PATCH 04/13] yarn-plugin: handle packing step This commit introduces a beforeWorkspacePacking hook which converts `backstage:` versions back into `npm:`` versions when packages are packed for publish. This allows the `backstage:` protocol to be used even for packages that are intended to themselves be published (such as packages in third-party Backstage plugin monorepos outside core). Signed-off-by: MT Lewis --- packages/yarn-plugin/package.json | 29 ++++---- packages/yarn-plugin/src/constants.ts | 17 +++++ .../src/handlers/beforeWorkspacePacking.ts | 66 +++++++++++++++++ packages/yarn-plugin/src/index.ts | 4 ++ .../src/resolver/BackstageResolver.ts | 43 +++-------- packages/yarn-plugin/src/util.ts | 71 +++++++++++++++++++ yarn.lock | 1 + 7 files changed, 185 insertions(+), 46 deletions(-) create mode 100644 packages/yarn-plugin/src/constants.ts create mode 100644 packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts create mode 100644 packages/yarn-plugin/src/util.ts diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index 713d7e5c49..817497a770 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -1,42 +1,43 @@ { "name": "yarn-plugin-backstage", - "description": "Yarn plugin for working with Backstage monorepos", "version": "0.0.0", - "private": true, + "description": "Yarn plugin for working with Backstage monorepos", "backstage": { "role": "node-library" }, + "private": true, + "keywords": [ + "backstage" + ], "homepage": "https://backstage.io", "repository": { "type": "git", "url": "https://github.com/backstage/backstage", "directory": "packages/yarn-plugin" }, - "keywords": [ - "backstage" - ], "license": "Apache-2.0", "main": "./src/index.ts", "scripts": { "build": "builder build plugin", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", - "start": "nodemon --" + "lint": "backstage-cli package lint", + "start": "nodemon --", + "test": "backstage-cli package test" + }, + "nodemonConfig": { + "exec": "builder build plugin", + "ext": "ts", + "watch": "./src" }, "dependencies": { "@backstage/release-manifests": "workspace:^", "@yarnpkg/core": "^4.0.3", - "@yarnpkg/fslib": "^3.0.2" + "@yarnpkg/fslib": "^3.0.2", + "semver": "^7.6.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@yarnpkg/builder": "^4.0.0", "nodemon": "^3.0.1" - }, - "nodemonConfig": { - "watch": "./src", - "exec": "builder build plugin", - "ext": "ts" } } diff --git a/packages/yarn-plugin/src/constants.ts b/packages/yarn-plugin/src/constants.ts new file mode 100644 index 0000000000..4473b1e347 --- /dev/null +++ b/packages/yarn-plugin/src/constants.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const PROTOCOL = 'backstage:'; diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts new file mode 100644 index 0000000000..80e663f17f --- /dev/null +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Descriptor, Workspace, structUtils } from '@yarnpkg/core'; +import { inferPackageVersion } from '../util'; +import { PROTOCOL } from '../constants'; + +const getFinalDependencyType = ( + dependencyType: string, + descriptor: Descriptor, + workspace: Workspace, +) => { + if (dependencyType !== 'dependencies') { + return dependencyType; + } + + return workspace.manifest.ensureDependencyMeta( + structUtils.makeDescriptor(descriptor, 'unknown'), + ).optional + ? 'optionalDependencies' + : dependencyType; +}; + +export const beforeWorkspacePacking = async ( + workspace: Workspace, + rawManifest: any, +) => { + for (const dependencyType of [ + 'dependencies', + 'devDependencies', + 'peerDependencies', + ] as const) { + const entries = Array.from( + workspace.manifest.getForScope(dependencyType).values(), + ).filter( + descriptor => + structUtils.parseRange(descriptor.range).protocol === PROTOCOL, + ); + + for (const descriptor of entries) { + const finalDependencyType = getFinalDependencyType( + dependencyType, + descriptor, + workspace, + ); + const ident = structUtils.stringifyIdent(descriptor); + + rawManifest[finalDependencyType][ident] = await inferPackageVersion( + descriptor, + ); + } + } +}; diff --git a/packages/yarn-plugin/src/index.ts b/packages/yarn-plugin/src/index.ts index aac855fadf..6c1c805fd8 100644 --- a/packages/yarn-plugin/src/index.ts +++ b/packages/yarn-plugin/src/index.ts @@ -22,12 +22,16 @@ */ import { Plugin } from '@yarnpkg/core'; +import { beforeWorkspacePacking } from './handlers/beforeWorkspacePacking'; import { BackstageResolver } from './resolver/BackstageResolver'; /** * @public */ const plugin: Plugin = { + hooks: { + beforeWorkspacePacking, + }, resolvers: [BackstageResolver], }; diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index 8a28c481ed..2bb16f8525 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -21,11 +21,11 @@ import { Package, Resolver, } from '@yarnpkg/core'; -import { xfs, npath } from '@yarnpkg/fslib'; -import { getManifestByVersion } from '@backstage/release-manifests'; +import { PROTOCOL } from '../constants'; +import { inferBackstageVersion, inferPackageVersion } from '../util'; export class BackstageResolver implements Resolver { - static protocol = `backstage:`; + static protocol = PROTOCOL; supportsDescriptor = (descriptor: Descriptor) => descriptor.range.startsWith(BackstageResolver.protocol); @@ -33,39 +33,18 @@ export class BackstageResolver implements Resolver { shouldPersistResolution = () => true; bindDescriptor(descriptor: Descriptor): Descriptor { - if (descriptor.range === `${BackstageResolver.protocol}*`) { - const backstageJson = xfs.readJsonSync( - npath.toPortablePath('./backstage.json'), - ); - - return structUtils.makeDescriptor( - descriptor, - `backstage:${backstageJson.version}`, - ); - } - - return descriptor; + return structUtils.makeDescriptor( + descriptor, + `backstage:${inferBackstageVersion(descriptor)}`, + ); } async getCandidates(descriptor: Descriptor): Promise { - const backstageVersion = descriptor.range.replace( - BackstageResolver.protocol, - '', - ); - - const manifest = await getManifestByVersion({ version: backstageVersion }); - const ident = structUtils.stringifyIdent(descriptor); - - const manifestEntry = manifest.packages.find( - candidate => candidate.name === ident, - ); - - if (!manifestEntry) { - throw new Error(`Package ${ident} not found in manifest`); - } - return [ - structUtils.makeLocator(descriptor, `npm:${manifestEntry.version}`), + structUtils.makeLocator( + descriptor, + `npm:${await inferPackageVersion(descriptor)}`, + ), ]; } diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts new file mode 100644 index 0000000000..25b760982b --- /dev/null +++ b/packages/yarn-plugin/src/util.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Descriptor, structUtils } from '@yarnpkg/core'; +import { npath, xfs } from '@yarnpkg/fslib'; +import { valid as semverValid } from 'semver'; +import { getManifestByVersion } from '@backstage/release-manifests'; +import { PROTOCOL } from './constants'; + +export const inferBackstageVersion = (descriptor: Descriptor) => { + const range = structUtils.parseRange(descriptor.range); + + if (range.protocol !== PROTOCOL) { + throw new Error( + `inferBackstageVersion called with unexpected protocol ${range.protocol}`, + ); + } + + let selector = range.selector; + + // For backstage:* we look up the version from backstage.json + if (selector === `*`) { + const backstageJson = xfs.readJsonSync( + npath.toPortablePath('./backstage.json'), + ); + + selector = backstageJson.version; + } + + if (!semverValid(selector)) { + throw new Error( + `Invalid "backstage:" version string found for ${structUtils.stringifyIdent( + descriptor, + )}. Version must be either "backstage:*" or "backstage:", where version is a single Backstage release version.`, + ); + } + + return selector; +}; + +export const inferPackageVersion = async (descriptor: Descriptor) => { + const ident = structUtils.stringifyIdent(descriptor); + const backstageVersion = inferBackstageVersion(descriptor); + + const manifest = await getManifestByVersion({ + version: backstageVersion, + }); + + const manifestEntry = manifest.packages.find( + candidate => candidate.name === ident, + ); + + if (!manifestEntry) { + throw new Error(`Package ${ident} not found in manifest`); + } + + return manifestEntry.version; +}; diff --git a/yarn.lock b/yarn.lock index 199462391b..b8cc660d66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45137,6 +45137,7 @@ __metadata: "@yarnpkg/core": ^4.0.3 "@yarnpkg/fslib": ^3.0.2 nodemon: ^3.0.1 + semver: ^7.6.0 languageName: unknown linkType: soft From 8fb936d9b0fc7a4c06739bc37aa0ed0d9f68d8f3 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Fri, 12 Apr 2024 21:34:24 +0100 Subject: [PATCH 05/13] yarn-plugin: add .gitignore for builder output Signed-off-by: MT Lewis --- packages/yarn-plugin/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 packages/yarn-plugin/.gitignore diff --git a/packages/yarn-plugin/.gitignore b/packages/yarn-plugin/.gitignore new file mode 100644 index 0000000000..fba89407fd --- /dev/null +++ b/packages/yarn-plugin/.gitignore @@ -0,0 +1,2 @@ +# @yarnpkg/builder build output +bundles/ From 038f851c28788733b8b0f29cabf40a03a9eb5c21 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Sun, 14 Apr 2024 20:40:57 +0100 Subject: [PATCH 06/13] yarn-plugin: support only "backstage:^" Signed-off-by: MT Lewis --- packages/yarn-plugin/README.md | 13 +++++++------ .../src/handlers/beforeWorkspacePacking.ts | 5 +---- .../yarn-plugin/src/resolver/BackstageResolver.ts | 2 +- packages/yarn-plugin/src/util.ts | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/yarn-plugin/README.md b/packages/yarn-plugin/README.md index dc3e509872..16507713af 100644 --- a/packages/yarn-plugin/README.md +++ b/packages/yarn-plugin/README.md @@ -1,12 +1,13 @@ # yarn-plugin-backstage This yarn plugin adds a `backstage:` version protocol to yarn, which replaces -specific version ranges for `@backstage/` packages. The recommended mode of use -is to set all versions strings to `backstage:*` in package.json, which causes -all versions to be resolved based on the version of Backstage specified in -`backstage.json`. This ensures that all `@backstage/` packages always correspond -to a single release, and removes the need for `package.json` files -to change when upgrading to a new release. +specific version ranges for `@backstage/` packages. The only version range +supported by this plugin is `backstage:^`, which has similar semantics to the +corresponding [`workspace` range](https://yarnpkg.com/features/workspaces#cross-references) when using +workspace dependencies; locally, the package will always resolve to the exact +version specified in the manifest for the Backstage release listed in +backstage.json. If the dependent package is published, this version will be +prefixed by `^`. **This plugin is still under active development, and requires some further testing before we recommend it for general use.** diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts index 80e663f17f..a98e8270a1 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts @@ -45,10 +45,7 @@ export const beforeWorkspacePacking = async ( ] as const) { const entries = Array.from( workspace.manifest.getForScope(dependencyType).values(), - ).filter( - descriptor => - structUtils.parseRange(descriptor.range).protocol === PROTOCOL, - ); + ).filter(descriptor => descriptor.range === `${PROTOCOL}^`); for (const descriptor of entries) { const finalDependencyType = getFinalDependencyType( diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index 2bb16f8525..61fbdab58e 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -35,7 +35,7 @@ export class BackstageResolver implements Resolver { bindDescriptor(descriptor: Descriptor): Descriptor { return structUtils.makeDescriptor( descriptor, - `backstage:${inferBackstageVersion(descriptor)}`, + `${PROTOCOL}${inferBackstageVersion(descriptor)}`, ); } diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index 25b760982b..ae11019c66 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -31,8 +31,8 @@ export const inferBackstageVersion = (descriptor: Descriptor) => { let selector = range.selector; - // For backstage:* we look up the version from backstage.json - if (selector === `*`) { + // For backstage:^ we look up the version from backstage.json + if (selector === `^`) { const backstageJson = xfs.readJsonSync( npath.toPortablePath('./backstage.json'), ); From 97ffd7ec18a737ac93a5765e6da42f71f4a87de4 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 16 Apr 2024 21:45:07 +0100 Subject: [PATCH 07/13] yarn-plugin: replace backstage:^ with ^ ranges when packing Signed-off-by: MT Lewis --- .../src/handlers/beforeWorkspacePacking.ts | 25 ++++++--- .../src/resolver/BackstageResolver.ts | 6 +-- packages/yarn-plugin/src/util.ts | 51 ++++++++----------- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts index a98e8270a1..e9f46a6159 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts @@ -15,7 +15,7 @@ */ import { Descriptor, Workspace, structUtils } from '@yarnpkg/core'; -import { inferPackageVersion } from '../util'; +import { getCurrentBackstageVersion, getPackageVersion } from '../util'; import { PROTOCOL } from '../constants'; const getFinalDependencyType = ( @@ -43,21 +43,34 @@ export const beforeWorkspacePacking = async ( 'devDependencies', 'peerDependencies', ] as const) { + const backstageVersion = getCurrentBackstageVersion(); + const entries = Array.from( workspace.manifest.getForScope(dependencyType).values(), - ).filter(descriptor => descriptor.range === `${PROTOCOL}^`); + ).filter(descriptor => descriptor.range.startsWith(PROTOCOL)); for (const descriptor of entries) { + const ident = structUtils.stringifyIdent(descriptor); + const range = structUtils.parseRange(descriptor.range); + + if (range.selector !== '^') { + throw new Error( + `Unexpected version range "${descriptor.range}" for dependency on "${ident}"`, + ); + } + const finalDependencyType = getFinalDependencyType( dependencyType, descriptor, workspace, ); - const ident = structUtils.stringifyIdent(descriptor); - rawManifest[finalDependencyType][ident] = await inferPackageVersion( - descriptor, - ); + rawManifest[finalDependencyType][ident] = `^${await getPackageVersion( + structUtils.makeDescriptor( + descriptor, + `${PROTOCOL}${backstageVersion}`, + ), + )}`; } } }; diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index 61fbdab58e..fa51ceb880 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -22,7 +22,7 @@ import { Resolver, } from '@yarnpkg/core'; import { PROTOCOL } from '../constants'; -import { inferBackstageVersion, inferPackageVersion } from '../util'; +import { getCurrentBackstageVersion, getPackageVersion } from '../util'; export class BackstageResolver implements Resolver { static protocol = PROTOCOL; @@ -35,7 +35,7 @@ export class BackstageResolver implements Resolver { bindDescriptor(descriptor: Descriptor): Descriptor { return structUtils.makeDescriptor( descriptor, - `${PROTOCOL}${inferBackstageVersion(descriptor)}`, + `${PROTOCOL}${getCurrentBackstageVersion()}`, ); } @@ -43,7 +43,7 @@ export class BackstageResolver implements Resolver { return [ structUtils.makeLocator( descriptor, - `npm:${await inferPackageVersion(descriptor)}`, + `npm:${await getPackageVersion(descriptor)}`, ), ]; } diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index ae11019c66..3e4e795c89 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -14,49 +14,40 @@ * limitations under the License. */ -import { Descriptor, structUtils } from '@yarnpkg/core'; import { npath, xfs } from '@yarnpkg/fslib'; import { valid as semverValid } from 'semver'; import { getManifestByVersion } from '@backstage/release-manifests'; +import { Descriptor, structUtils } from '@yarnpkg/core'; import { PROTOCOL } from './constants'; -export const inferBackstageVersion = (descriptor: Descriptor) => { +export const getCurrentBackstageVersion = () => { + const backstageJson = xfs.readJsonSync( + npath.toPortablePath('./backstage.json'), + ); + + const backstageVersion = semverValid(backstageJson.version); + + if (backstageVersion === null) { + throw new Error('Valid version string not found in backstage.json'); + } + + return backstageVersion; +}; + +export const getPackageVersion = async (descriptor: Descriptor) => { + const ident = structUtils.stringifyIdent(descriptor); const range = structUtils.parseRange(descriptor.range); if (range.protocol !== PROTOCOL) { - throw new Error( - `inferBackstageVersion called with unexpected protocol ${range.protocol}`, - ); + throw new Error(`Unexpected ${range.protocol} range when packing`); } - let selector = range.selector; - - // For backstage:^ we look up the version from backstage.json - if (selector === `^`) { - const backstageJson = xfs.readJsonSync( - npath.toPortablePath('./backstage.json'), - ); - - selector = backstageJson.version; + if (!semverValid(range.selector)) { + throw new Error(`Missing backstage version in range ${descriptor.range}`); } - if (!semverValid(selector)) { - throw new Error( - `Invalid "backstage:" version string found for ${structUtils.stringifyIdent( - descriptor, - )}. Version must be either "backstage:*" or "backstage:", where version is a single Backstage release version.`, - ); - } - - return selector; -}; - -export const inferPackageVersion = async (descriptor: Descriptor) => { - const ident = structUtils.stringifyIdent(descriptor); - const backstageVersion = inferBackstageVersion(descriptor); - const manifest = await getManifestByVersion({ - version: backstageVersion, + version: range.selector, }); const manifestEntry = manifest.packages.find( From 831b0e631406f726fc00452978ccf292158ae0ce Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 18 Apr 2024 10:09:35 +0100 Subject: [PATCH 08/13] yarn-plugin: do not attempt to convert backstage: versions in peerDependencies Yarn does not support protocols other than npm and workspace for peerDependencies - any other protocols will produce an error and be converted to '*' when running yarn. This change matches that limitation in the beforeWorkspacePacking hook. Signed-off-by: MT Lewis --- .../yarn-plugin/src/handlers/beforeWorkspacePacking.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts index e9f46a6159..b804f64226 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.ts @@ -38,13 +38,9 @@ export const beforeWorkspacePacking = async ( workspace: Workspace, rawManifest: any, ) => { - for (const dependencyType of [ - 'dependencies', - 'devDependencies', - 'peerDependencies', - ] as const) { - const backstageVersion = getCurrentBackstageVersion(); + const backstageVersion = getCurrentBackstageVersion(); + for (const dependencyType of ['dependencies', 'devDependencies'] as const) { const entries = Array.from( workspace.manifest.getForScope(dependencyType).values(), ).filter(descriptor => descriptor.range.startsWith(PROTOCOL)); From 7763950ed55c579297122f2257edfa2dbb1d916e Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 18 Apr 2024 10:11:02 +0100 Subject: [PATCH 09/13] yarn-plugin: ensure getCurrentBackstageVersion works anywhere in the workspace Previously this method only worked in the workspace root. A bit verbose and manual to make this work, because it needs to be synchronous. Signed-off-by: MT Lewis --- packages/yarn-plugin/src/util.ts | 35 ++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index 3e4e795c89..5d13315327 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -14,15 +14,46 @@ * limitations under the License. */ -import { npath, xfs } from '@yarnpkg/fslib'; +import { PortablePath, ppath, xfs } from '@yarnpkg/fslib'; import { valid as semverValid } from 'semver'; import { getManifestByVersion } from '@backstage/release-manifests'; import { Descriptor, structUtils } from '@yarnpkg/core'; import { PROTOCOL } from './constants'; +const isWorkspaceRoot = (dir: PortablePath) => { + const manifestPath = ppath.join(dir, 'package.json'); + + if (xfs.existsSync(manifestPath)) { + const manifest = xfs.readJsonSync(manifestPath); + + if (manifest.workspaces) { + return true; + } + } + + return false; +}; + +const findWorkspaceRoot = () => { + const cwd = ppath.cwd(); + let currentDir = cwd; + + while (!isWorkspaceRoot(currentDir)) { + const parentDir = ppath.dirname(currentDir); + + if (parentDir === currentDir) { + throw new Error(`Workspace root not found from ${cwd}`); + } + + currentDir = parentDir; + } + + return currentDir; +}; + export const getCurrentBackstageVersion = () => { const backstageJson = xfs.readJsonSync( - npath.toPortablePath('./backstage.json'), + ppath.join(findWorkspaceRoot(), 'backstage.json'), ); const backstageVersion = semverValid(backstageJson.version); From c24bc371eb1c403766218574d9dfb48950a67c76 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Thu, 18 Apr 2024 10:11:59 +0100 Subject: [PATCH 10/13] yarn-plugin: add unit tests Signed-off-by: MT Lewis --- packages/yarn-plugin/package.json | 1 + .../handlers/beforeWorkspacePacking.test.ts | 120 ++++++++++++ .../src/resolver/BackstageResolver.test.ts | 177 ++++++++++++++++++ .../src/resolver/BackstageResolver.ts | 28 +++ yarn.lock | 1 + 5 files changed, 327 insertions(+) create mode 100644 packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts create mode 100644 packages/yarn-plugin/src/resolver/BackstageResolver.test.ts diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index 817497a770..5b4d8f3aea 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -36,6 +36,7 @@ "semver": "^7.6.0" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@yarnpkg/builder": "^4.0.0", "nodemon": "^3.0.1" diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts new file mode 100644 index 0000000000..f5f15b861b --- /dev/null +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Manifest, Workspace } from '@yarnpkg/core'; +import { npath, ppath } from '@yarnpkg/fslib'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +import { beforeWorkspacePacking } from './beforeWorkspacePacking'; + +jest.mock('@backstage/release-manifests', () => ({ + getManifestByVersion: jest.fn().mockResolvedValue({ + releaseVersion: '1.23.45', + packages: [ + { + name: '@backstage/core', + version: '3.2.1', + }, + ], + }), +})); + +const makeWorkspace = (manifest: object) => { + return { + manifest: Manifest.fromText(JSON.stringify(manifest)), + } as Workspace; +}; + +describe('beforeWorkspacePacking', () => { + const mockDir = createMockDirectory(); + + beforeEach(() => { + jest + .spyOn(ppath, 'cwd') + .mockReturnValue(npath.toPortablePath(mockDir.path)); + + mockDir.setContent({ + 'backstage.json': JSON.stringify({ + version: '1.23.45', + }), + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + }); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + describe.each` + dependencyType + ${'dependencies'} + ${'devDependencies'} + ${'optionalDependencies'} + `('$dependencyType', ({ dependencyType }) => { + it(`ignores ${dependencyType} that don't use the backstage: protocol`, () => { + const result = { + name: 'test-package', + [dependencyType]: { + foo: '^1.1.1', + }, + }; + + beforeWorkspacePacking(makeWorkspace(result), result); + + expect(result).toEqual({ + name: 'test-package', + [dependencyType]: { + foo: '^1.1.1', + }, + }); + }); + + it(`throws an error for any backstage: versions with a selector other than ^`, async () => { + const result = { + name: 'test-package', + [dependencyType]: { + '@backstage/core': 'backstage:^1.1.1', + }, + }; + + await expect(() => + beforeWorkspacePacking(makeWorkspace(result), result), + ).rejects.toThrow(); + }); + + it('converts backstage:^ versions to the corresponding package version prefixed by ^', async () => { + const result = { + name: 'test-package', + [dependencyType]: { + '@backstage/core': 'backstage:^', + }, + }; + + await beforeWorkspacePacking(makeWorkspace(result), result); + + expect(result).toEqual({ + name: 'test-package', + [dependencyType]: { + '@backstage/core': '^3.2.1', + }, + }); + }); + }); +}); diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts new file mode 100644 index 0000000000..9aad0cbc09 --- /dev/null +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts @@ -0,0 +1,177 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { structUtils } from '@yarnpkg/core'; +import { npath, ppath } from '@yarnpkg/fslib'; +import { BackstageResolver } from './BackstageResolver'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +jest.mock('@backstage/release-manifests', () => ({ + getManifestByVersion: jest.fn().mockResolvedValue({ + releaseVersion: '1.23.45', + packages: [ + { + name: '@backstage/core', + version: '6.7.8', + }, + ], + }), +})); + +describe('BackstageResolver', () => { + const mockDir = createMockDirectory(); + let backstageResolver: BackstageResolver; + + beforeEach(() => { + jest + .spyOn(ppath, 'cwd') + .mockReturnValue(npath.toPortablePath(mockDir.path)); + + mockDir.setContent({ + 'backstage.json': JSON.stringify({ + version: '1.23.45', + }), + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': 'backstage:^', + }, + }), + }, + }, + }); + + backstageResolver = new BackstageResolver(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + describe('supportsDescriptor', () => { + it.each([ + ['backstage:^'], + ['backstage:1.26.0-next.3'], + ['backstage:anything'], + ])('returns true for range "%s"', range => { + expect( + backstageResolver.supportsDescriptor( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + range, + ), + ), + ).toEqual(true); + }); + }); + + describe('bindDescriptor', () => { + describe('with range "backstage:^"', () => { + it('returns a descriptor basedwith a version range for the current Backstage version', () => { + expect( + backstageResolver.bindDescriptor( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:^', + ), + ), + ).toEqual( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:1.23.45', + ), + ); + }); + }); + + describe('with range "backstage:1.23.45"', () => { + it('throws an error', () => { + expect(() => + backstageResolver.bindDescriptor( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:1.23.45', + ), + ), + ).toThrow(/unsupported version range/i); + }); + }); + }); + + describe('getCandidates', () => { + it('returns an npm: descriptor based on the manifest for the appropriate backstage version', async () => { + const descriptor = structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:1.23.45', + ); + + await expect( + backstageResolver.getCandidates(descriptor), + ).resolves.toEqual([structUtils.makeLocator(descriptor, 'npm:6.7.8')]); + }); + + it('rejects descriptors not using the backstage: protocol', async () => { + await expect( + backstageResolver.getCandidates( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'npm:1.2.3', + ), + ), + ).rejects.toThrow(/unsupported version protocol/i); + }); + + it('rejects backstage: ranges with a ^ shorthand version', async () => { + await expect( + backstageResolver.getCandidates( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:^', + ), + ), + ).rejects.toThrow(/invalid backstage version/i); + }); + + it('rejects backstage: ranges with a * shorthand version', async () => { + await expect( + backstageResolver.getCandidates( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:*', + ), + ), + ).rejects.toThrow(/invalid backstage version/i); + }); + + it('rejects backstage: ranges with an invalid version specified', async () => { + await expect( + backstageResolver.getCandidates( + structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:latest', + ), + ), + ).rejects.toThrow(/invalid backstage version/i); + }); + }); +}); diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index fa51ceb880..3a56124fe3 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -21,6 +21,7 @@ import { Package, Resolver, } from '@yarnpkg/core'; +import semver from 'semver'; import { PROTOCOL } from '../constants'; import { getCurrentBackstageVersion, getPackageVersion } from '../util'; @@ -33,6 +34,16 @@ export class BackstageResolver implements Resolver { shouldPersistResolution = () => true; bindDescriptor(descriptor: Descriptor): Descriptor { + if (descriptor.range !== 'backstage:^') { + throw new Error( + `Unsupported version range "${ + descriptor.range + }" for package ${structUtils.stringifyIdent( + descriptor, + )}. The backstage protocol only supports the range "backstage:^".`, + ); + } + return structUtils.makeDescriptor( descriptor, `${PROTOCOL}${getCurrentBackstageVersion()}`, @@ -40,6 +51,23 @@ export class BackstageResolver implements Resolver { } async getCandidates(descriptor: Descriptor): Promise { + const range = structUtils.parseRange(descriptor.range); + if (range.protocol !== BackstageResolver.protocol) { + throw new Error( + `Unsupported version protocol in version range "${ + descriptor.range + }" for package ${structUtils.stringifyIdent(descriptor)}`, + ); + } + + if (!semver.valid(range.selector)) { + throw new Error( + `Invalid Backstage version string when resolving version for ${structUtils.stringifyIdent( + descriptor, + )}`, + ); + } + return [ structUtils.makeLocator( descriptor, diff --git a/yarn.lock b/yarn.lock index b8cc660d66..9ff777da8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45131,6 +45131,7 @@ __metadata: version: 0.0.0-use.local resolution: "yarn-plugin-backstage@workspace:packages/yarn-plugin" dependencies: + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/release-manifests": "workspace:^" "@yarnpkg/builder": ^4.0.0 From acc7caa7151b88c21a6a1f986e034b8ad534c420 Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 4 Jun 2024 16:32:44 +0100 Subject: [PATCH 11/13] yarn-plugin: add some explanatory comments to BackstageResolver Signed-off-by: MT Lewis --- .../src/resolver/BackstageResolver.ts | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.ts index 3a56124fe3..33bba5df53 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.ts @@ -33,6 +33,16 @@ export class BackstageResolver implements Resolver { shouldPersistResolution = () => true; + /** + * Called for each dependency present in the dependency list of a package + * definition. If it returns a new descriptor, this new descriptor will be + * used. + * + * In this plugin, we convert the specific range "backstage:^" to + * "backstage:". This new range will be the one + * stored in lockfile entries, ensuring that we re-resolve the package when + * the version in backstage.json changes. + */ bindDescriptor(descriptor: Descriptor): Descriptor { if (descriptor.range !== 'backstage:^') { throw new Error( @@ -50,6 +60,12 @@ export class BackstageResolver implements Resolver { ); } + /** + * Given a descriptor, return the list of locators that potentially satisfy + * it. The implementation in this plugin converts a `backstage:` range with a + * concrete version into the appropriate concrete npm version for that + * backstage release. + */ async getCandidates(descriptor: Descriptor): Promise { const range = structUtils.parseRange(descriptor.range); if (range.protocol !== BackstageResolver.protocol) { @@ -76,19 +92,33 @@ export class BackstageResolver implements Resolver { ]; } + /** + * This plugin does not need to support any locators itself, since the + * `getCandidates` method will always convert `backstage:` versions into + * `npm:` versions which can be handled as usual. + */ supportsLocator = () => false; + /** + * This resolver never transforms the packages that are actually depended on, + * only replaces versions. As such there's never a need to add additional + * dependencies. + */ getResolutionDependencies = () => ({}); + /** + * Candidate versions produced by this resolver always use the `npm:` + * protocol, so this function will never be called. + */ async getSatisfying(): Promise<{ locators: Locator[]; sorted: boolean }> { - // Candidate versions produced by this resolver always use the `npm:` - // protocol, so this function will never be called. throw new Error('Unreachable'); } + /** + * Once transformed into locators (through getCandidates), the versions are + * resolved by the NpmSemverResolver + */ async resolve(): Promise { - // Once transformed into locators (through getCandidates), the versions are - // resolved by the NpmSemverResolver throw new Error(`Unreachable`); } } From 95d7234e91392e1ff8feb0ba7e473658e2f3cb2a Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 4 Jun 2024 16:39:07 +0100 Subject: [PATCH 12/13] yarn-plugin: expand error message when package is missing from version manifest Signed-off-by: MT Lewis --- packages/yarn-plugin/src/util.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index 5d13315327..3ee544289f 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -86,7 +86,14 @@ export const getPackageVersion = async (descriptor: Descriptor) => { ); if (!manifestEntry) { - throw new Error(`Package ${ident} not found in manifest`); + throw new Error( + `Package ${ident} not found in manifest for Backstage v${range.selector}. ` + + `This means the specified package is not included in this Backstage ` + + `release. This may imply the package has been replaced with an alternative - ` + + `please review the documentation for the package. If you need to continue ` + + `using this package, it will be necessary to switch to manually managing its ` + + `version.`, + ); } return manifestEntry.version; From 573e98b352484183a8c96e37aad7f771bcd9235c Mon Sep 17 00:00:00 2001 From: MT Lewis Date: Tue, 4 Jun 2024 17:01:59 +0100 Subject: [PATCH 13/13] yarn-plugin: use findPaths from cli-common instead of custom findWorkspaceRoot implementation Signed-off-by: MT Lewis --- packages/yarn-plugin/package.json | 1 + .../handlers/beforeWorkspacePacking.test.ts | 4 ++ .../src/resolver/BackstageResolver.test.ts | 4 ++ packages/yarn-plugin/src/util.ts | 38 +++---------------- yarn.lock | 1 + 5 files changed, 15 insertions(+), 33 deletions(-) diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index 5b4d8f3aea..b6b97c0475 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -30,6 +30,7 @@ "watch": "./src" }, "dependencies": { + "@backstage/cli-common": "workspace:^", "@backstage/release-manifests": "workspace:^", "@yarnpkg/core": "^4.0.3", "@yarnpkg/fslib": "^3.0.2", diff --git a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts index f5f15b861b..ca99b88437 100644 --- a/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts +++ b/packages/yarn-plugin/src/handlers/beforeWorkspacePacking.test.ts @@ -46,6 +46,10 @@ describe('beforeWorkspacePacking', () => { .spyOn(ppath, 'cwd') .mockReturnValue(npath.toPortablePath(mockDir.path)); + jest + .spyOn(process, 'cwd') + .mockReturnValue(npath.toPortablePath(mockDir.path)); + mockDir.setContent({ 'backstage.json': JSON.stringify({ version: '1.23.45', diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts index 9aad0cbc09..4cc0c1c9f2 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts @@ -40,6 +40,10 @@ describe('BackstageResolver', () => { .spyOn(ppath, 'cwd') .mockReturnValue(npath.toPortablePath(mockDir.path)); + jest + .spyOn(process, 'cwd') + .mockReturnValue(npath.toPortablePath(mockDir.path)); + mockDir.setContent({ 'backstage.json': JSON.stringify({ version: '1.23.45', diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index 3ee544289f..8431e23cfa 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -14,46 +14,18 @@ * limitations under the License. */ -import { PortablePath, ppath, xfs } from '@yarnpkg/fslib'; +import { ppath, xfs } from '@yarnpkg/fslib'; import { valid as semverValid } from 'semver'; import { getManifestByVersion } from '@backstage/release-manifests'; +import { BACKSTAGE_JSON, findPaths } from '@backstage/cli-common'; import { Descriptor, structUtils } from '@yarnpkg/core'; import { PROTOCOL } from './constants'; -const isWorkspaceRoot = (dir: PortablePath) => { - const manifestPath = ppath.join(dir, 'package.json'); - - if (xfs.existsSync(manifestPath)) { - const manifest = xfs.readJsonSync(manifestPath); - - if (manifest.workspaces) { - return true; - } - } - - return false; -}; - -const findWorkspaceRoot = () => { - const cwd = ppath.cwd(); - let currentDir = cwd; - - while (!isWorkspaceRoot(currentDir)) { - const parentDir = ppath.dirname(currentDir); - - if (parentDir === currentDir) { - throw new Error(`Workspace root not found from ${cwd}`); - } - - currentDir = parentDir; - } - - return currentDir; -}; - export const getCurrentBackstageVersion = () => { + const workspaceRoot = ppath.resolve(findPaths(ppath.cwd()).targetRoot); + const backstageJson = xfs.readJsonSync( - ppath.join(findWorkspaceRoot(), 'backstage.json'), + ppath.join(workspaceRoot, BACKSTAGE_JSON), ); const backstageVersion = semverValid(backstageJson.version); diff --git a/yarn.lock b/yarn.lock index 9ff777da8c..9f00d91e00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45133,6 +45133,7 @@ __metadata: dependencies: "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/cli-common": "workspace:^" "@backstage/release-manifests": "workspace:^" "@yarnpkg/builder": ^4.0.0 "@yarnpkg/core": ^4.0.3