Skip to content

[ENHANCEMENT] add ability to clone a semver instance #378

Open

Description

@madhead

What / Why

I'm trying to compute a bunch of various increments for a specific version (TypeScript):

console.log(version.inc('major'))
console.log(version.inc('minor'))
console.log(version.inc('patch'))

The problem is the SemVer class itself is mutable, so each increment is computed against previous increment result. This is not what I need.

So, I need a way to clone this object, like.

console.log(new SemVer(version).inc('major'))
console.log(new SemVer(version).inc('minor'))
console.log(new SemVer(version).inc('patch'))

But the constructor of the SemVer (new SemVer(version)) doesn't create a new instance when passed another instance with the same options. So, again, the code doesn't work.

Is there a way to clone a SemVer?

Activity

  1. pigulla commented on May 20, 2021

    @pigulla

    I'd also be interested in this. Did you find a solution?

  2. madhead commented on May 20, 2021

    @madhead
    Author

    Unfortunately, no, I had to store the components separately and use them to construct new instances.

  3. rauno56 commented on Jan 15, 2022

    @rauno56

    When the version is a string, it works as you expect it to @madhead, @pigulla.

    {
      // works as you expect:
      const version = '1.2.3';
      console.log(new SemVer(version).inc('major'))
      console.log(new SemVer(version).inc('minor'))
      console.log(new SemVer(version).inc('patch'))
    }
    
    {
      // When you already have a SemVer object and want to copy it, pass "version"
      const semVersion = new SemVer('1.2.3');
      console.log(new SemVer(semVersion.version).inc('major'))
      console.log(new SemVer(semVersion.version).inc('minor'))
      console.log(new SemVer(semVersion.version).inc('patch'))
    }
  4. madhead commented on Apr 5, 2022

    @madhead
    Author

    No fix, just closing?

  5. lukekarrys commented on Apr 5, 2022

    @lukekarrys
    Contributor

    The previous comment is the best answer to the question at this time, since there is no way to fully clone a semver instance (with options). I would recommend making a wrapper function that takes a version and options and always returns a new instance. We don't have any plans at this time to add a new method to clone an instance.

  6. ljharb commented on Apr 5, 2022

    @ljharb
    Contributor

    @lukekarrys it kind of seems like this then is a feature request to add that? something like new Semver(instance) or Semver.clone(instance)

  7. lukekarrys commented on Apr 5, 2022

    @lukekarrys
    Contributor

    I think new SemVer(instance) cloning the existing instance would be a breaking change, that I would rather not make. A static method on the class would make more sense, but I'm still hesitant to add api surface area. A PR or new issue with this feature proposal could get more input as to whether it should be added or not.

    fwiw here's what I was thinking previously for a wrapper function:

    const clone = (v) => new SemVer(v.version ?? v, v.options)
    
  8. ljharb commented on Apr 5, 2022

    @ljharb
    Contributor

    i'd expect v => v instanceof Semver ? new Semver(v.version, v.options) : new Semver(v).

    i'm not sure why it'd be a breaking change; do you think anyone's relying on new Semver(instance) if it doesn't work right now?

  9. lukekarrys commented on Apr 6, 2022

    @lukekarrys
    Contributor

    i'm not sure why it'd be a breaking change

    I'm erring on the side of caution, and not knowing the history of the decision. It appears to be an explicit design decision to reuse an instance (and I traced this back to at least v2.0.0)

    if (version instanceof SemVer) {
    if (version.loose === !!options.loose &&
    version.includePrerelease === !!options.includePrerelease) {
    return version
    } else {
    version = version.version
    }

    if it doesn't work right now?

    It does work to do new Semver(instance) it just returns instance (if the options match).

    I can imagine situations for a highly used library like this, in which this would be a breaking change. Even the fact that this would break strict equality checks, makes me lean towards breaking change.

    const s = new SemVer('1.0.0')
    s === new SemVer(s) // true
  10. ljharb commented on Apr 6, 2022

    @ljharb
    Contributor

    Fair point.

  11. changed the title [-][QUESTION] How do I clone a SemVer?[/-] [+][ENHANCEMENT] add ability to clone a semver instance[/+] on Oct 27, 2022
  12. lukekarrys commented on Oct 27, 2022

    @lukekarrys
    Contributor

    Reopening this and labeling as semver:major so we don't forget to figure out a proper API for this in the future. It might not end up being a breaking change, but grouping it with the rest of the semver:major issues will help.

  13. added this to the v8 milestone on Oct 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    semver:majorbackwards-incompatible breaking changes

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions