Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

coerce drops build and prerelease information #592

Closed
tim-neo opened this issue Jul 10, 2023 · 6 comments · Fixed by #671
Closed

coerce drops build and prerelease information #592

tim-neo opened this issue Jul 10, 2023 · 6 comments · Fixed by #671

Comments

@tim-neo
Copy link

tim-neo commented Jul 10, 2023

Hi there 👋

I am currently using semver.coerce to coerce semver-like strings into a string which only contains a major, minor, and patch version.

The documentation doesn't mention anything about the other things which semver.parse may produce (build number, prerelease, etc.).
...is it safe for me to depend on this behaviour? Is there a better way to do this?

In addition, I need to coerce a lot of strings missing a patch version:

>require('semver').coerce('10.20-45')
SemVer {
  options: {},
  loose: false,
  raw: '10.20.0',
  major: 10,
  minor: 20,
  patch: 0,
  prerelease: [],
  build: [],
  version: '10.20.0'
}

The reason I am asking is because of somewhat surprising results. While I don't want the current behaviour of semver to change, I think if this is too surprising maybe it should. What do you think? 🤔

Welcome to Node.js v16.20.0.
Type ".help" for more information.
> const semver = require('semver')
undefined
> const semverStringWithPrerelease = '10.20.30-40';
undefined
> semver.valid(semverStringWithPrerelease);
'10.20.30-40'
> semver.parse(semverStringWithPrerelease);
SemVer {
  options: { loose: false, includePrerelease: false },
  loose: false,
  raw: '10.20.30-40',
  major: 10,
  minor: 20,
  patch: 30,
  prerelease: [ 40 ],
  build: [],
  version: '10.20.30-40'
}
> semver.coerce(semverStringWithPrerelease);
SemVer {
  options: {},
  loose: false,
  raw: '10.20.30',
  major: 10,
  minor: 20,
  patch: 30,
  prerelease: [],
  build: [],
  version: '10.20.30'
}
> semver.compare(semverStringWithPrerelease, semverStringWithPrerelease)
0
> semver.compare(semver.coerce(semverStringWithPrerelease), semverStringWithPrerelease)
1
@mbtools
Copy link
Contributor

mbtools commented Jul 11, 2023

Hi Tim,

indeed, coerce extracts only major, minor, and patch numbers. Anything else is ignored. It does exactly what you describe in your first sentence.

node-semver/internal/re.js

Lines 155 to 161 in 36cd334

// Coercion.
// Extract anything that could conceivably be a part of a valid semver
createToken('COERCE', `${'(^|[^\\d])' +
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
`(?:$|[^\\d])`)

If minor or patch are missing, they are replaced with 0.

@tim-neo
Copy link
Author

tim-neo commented Jul 11, 2023

Hi Tim,

indeed, coerce extracts only major, minor, and patch numbers. Anything else is ignored. It does exactly what you describe in your first sentence.

node-semver/internal/re.js

Lines 155 to 161 in 36cd334

// Coercion.
// Extract anything that could conceivably be a part of a valid semver
createToken('COERCE', `${'(^|[^\\d])' +
'(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` +
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
`(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` +
`(?:$|[^\\d])`)

If minor or patch are missing, they are replaced with 0.

Interesting, I am curious, what do you think of my "surprising results" ?

To me it means that a use case of coerce that seems natural is now not possible:

As a user of Semver, I want to coerce version strings which may not be compatible before I use them with compare.
Given I pass a valid Semver string to coerce and receive a result that is now guaranteed to be a valid Semver,
When I pass the resultant Semver to compare to compare it with another valid Semver,
I get the same result I would have gotten without using coerce.

Because this is surprising to me, I think it may be worth mentioning the behaviour in the documentation. There is an example for how it handles 4.6.3.9.2-alpha2, but that is not a valid Semver String. If there was an example with a valid one, like 4.6.3-alpha2, it would be obvious to me that this behaviour is intended.

What do you think?

@mbtools
Copy link
Contributor

mbtools commented Jul 12, 2023

You could propose changing "Longer versions are simply truncated" to "Only major, minor, and patch are taken into consideration. Longer versions are simply truncated". Feel free to create a PR.

madtisa pushed a commit to madtisa/node-semver that referenced this issue Dec 21, 2023
…m#592)

Introduces the new coerce option `full`, if set, allowing to preserve
pre-release and build parts of a version.
madtisa pushed a commit to madtisa/node-semver that referenced this issue Dec 22, 2023
…m#592)

Introduces the new coerce option `full`, if set, allowing to preserve
pre-release and build parts of a version.
wraithgar added a commit that referenced this issue Jan 31, 2024
# What / Why

Introduces the new coerce option `includePrerelease`, if set, allowing
to preserve pre-release and build parts of a version.

## References

Fixes #592
Fixes #357

---------

Co-authored-by: madtisa <temp-email-for-oauth-madtisa@gitlab.localhost>
Co-authored-by: Gar <wraithgar@github.com>
@miwo00097

This comment was marked as spam.

@miwo00097

This comment was marked as spam.

@miwo00097

This comment was marked as spam.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants