From aeb8be3263a045d43effa5c4f87342d28e137b94 Mon Sep 17 00:00:00 2001 From: Flippie Scholtz Date: Wed, 26 Jul 2023 15:02:21 +0200 Subject: [PATCH 1/2] feat: support non-semver versions in the yarn packager, for example 'github:' references --- src/packagers/yarn.ts | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/packagers/yarn.ts b/src/packagers/yarn.ts index 1df808f8..fe4ca276 100644 --- a/src/packagers/yarn.ts +++ b/src/packagers/yarn.ts @@ -1,5 +1,5 @@ import { any, isEmpty, reduce, replace, split, startsWith } from 'ramda'; -import { satisfies } from 'semver'; +import { satisfies, valid as isValidSemver } from 'semver'; import type { DependenciesResult, DependencyMap, PackagerOptions } from '../types'; import { SpawnError, spawnProcess } from '../utils'; @@ -23,11 +23,27 @@ export interface YarnDeps { } const getNameAndVersion = (name: string): { name: string; version: string } => { - const atIndex = name.lastIndexOf('@'); + /* + * This regex supports these cases: + * - package@version (single '@' is the separator) => returns 'package' + * - @org/package@version ('@' for org name and version separator) => returns '@org/package' + * - @org/package@git+ssh://git@github.com/org/package (last '@' is not a name / version separator) => returns '@org/package' + */ + const packageNameMatch = name.match(/^(@[^@]+|[^@]+)/); + + if (!packageNameMatch) { + return { + name, + version: '', + }; + } + + // Everything after the name is the version (separated by a single '@'): + const versionStartIndex = (packageNameMatch?.index || 0) + packageNameMatch[0].length; return { - name: name.slice(0, atIndex), - version: name.slice(atIndex + 1), + name: packageNameMatch[0], + version: name.slice(versionStartIndex), }; }; @@ -134,7 +150,8 @@ export class Yarn implements Packager { if (tree.shadow) { // Package is resolved somewhere else - if (dependency && satisfies(dependency.version, version)) { + // If the version is not valid semver, include the package by default. For e.g. 'github:' references where semver doesn't apply. + if (dependency && (satisfies(dependency.version, version) || !isValidSemver(dependency.version))) { // Package is at root level // { // "name": "samchungy-dep-a@1.0.0", <- MATCH From 248368e09a843453d280489c78ecf3490190cdde Mon Sep 17 00:00:00 2001 From: Flippie Scholtz Date: Wed, 26 Jul 2023 17:47:35 +0200 Subject: [PATCH 2/2] fix: off-by-one error in yarn packager version parsing code, fix semver comparison --- src/packagers/yarn.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/packagers/yarn.ts b/src/packagers/yarn.ts index fe4ca276..432beb2f 100644 --- a/src/packagers/yarn.ts +++ b/src/packagers/yarn.ts @@ -39,7 +39,7 @@ const getNameAndVersion = (name: string): { name: string; version: string } => { } // Everything after the name is the version (separated by a single '@'): - const versionStartIndex = (packageNameMatch?.index || 0) + packageNameMatch[0].length; + const versionStartIndex = (packageNameMatch?.index || 0) + packageNameMatch[0].length + 1; return { name: packageNameMatch[0], @@ -150,8 +150,11 @@ export class Yarn implements Packager { if (tree.shadow) { // Package is resolved somewhere else - // If the version is not valid semver, include the package by default. For e.g. 'github:' references where semver doesn't apply. - if (dependency && (satisfies(dependency.version, version) || !isValidSemver(dependency.version))) { + // If either version is not valid semver, we can't compare, so include the package by default. For e.g. 'github:' references where semver doesn't apply. + if ( + dependency && + (satisfies(dependency.version, version) || !isValidSemver(dependency.version) || !isValidSemver(version)) + ) { // Package is at root level // { // "name": "samchungy-dep-a@1.0.0", <- MATCH