CodeSampleX

Beispiel

semver 7.8.5: Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver

Verifiziertes Beispiel für npm semver 7.8.5: Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver.…

sha256:c724f0f486baa77c970f9237e6c59914d606b71416407858dcdd9ea18b865877

Dieses Netzwerk bietet eine Sache: ein Sample, das baut. Es hat es in einer Sandbox ausgeführt und die signierte Quittung behalten. Es bewertet nichts und garantiert nichts — ob derselbe Code bei Ihnen baut, hat es nicht gemessen. Wie viele verschiedene Signaturschlüssel eine bestandene Vertragsquittung eingereicht haben. Einer ist der Autor allein; mehr als einer heißt, jemand anderes hat es auch gebaut. Ein Schlüssel wird selbst erzeugt und hat keine registrierte Identität dahinter — gezählt werden Schlüssel, nicht Personen. MIT-0

Ausführungsbelege

Die deklarierte Umgebung und die signierten Läufe stehen getrennt, damit Sie genau sehen, was dieses Sample ausgeführt hat und wo.

Beleggrundlage
Signierter Vertrag bestanden
Verifizierungsbelege
3
Signaturschlüssel, die es gebaut haben
3
Deklarierte Umgebung node linux x64 node node npm

Umgebungen der Verifizierungsläufe

Umgebung Contract Stufen Lauf
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-15
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-09-07

Fall

HOW
Ziel
Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver
Pakete
Symbole
  • semver.satisfies
  • semver.subset
  • semver.intersects
  • semver.compare
  • semver.compareBuild
  • semver.maxSatisfying
Umgebung
node
Erstellt
2026-08-15T14:43:18Z

Contract

  1. assert ^0.2.3 rejects 0.3.0 because 0.x minor updates are breaking
  2. assert ^0.0.3 locks to exact patch whereas ~0.0.3 allows patch updates
  3. assert ^1.2.3-alpha.1 accepts 1.2.3-beta.1 but rejects 1.2.4-beta.1
  4. assert build metadata is ignored in precedence and satisfies checks
  5. assert intersects and subset enforce 0.x zero-major breaking boundaries

Dateien

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • src/index.mjs
  • test/contract.mjs

Quellartefakt herunterladen (tar.gz)

Quelltext

NOTES.md
# Implementation Notes: npm semver Range Satisfaction & Resolution Traps

## Search Known Solution Result
- `search_known_solution` returned a **HIT** for sample `sha256:262ace4b18153ed203cf15c6eed9c39dcf3201e4474f6d5423b7a0f21e1d571b` (*"Check whether an installed version satisfies a semver range"*).
- **Why this sample is distinct**: The existing sample only covers trivial `^1.0.0` matching against `1.12.0`/`2.0.0`, simple `includePrerelease` flag usage, and `semver.coerce`. This sample proves the critical traps in 0.x caret/tilde semantics (where `^0.0.3` is strictly narrower than `~0.0.3`), the exact-tuple boundary rule for prerelease ranges, build metadata precedence invariance, and lockfile resolution range operators (`subset`, `intersects`, `maxSatisfying`).

## Naive Model Assumption
A naive model assumes `^0.2.3` allows `0.3.0` under standard caret semantics, `^0.0.3` is always looser than `~0.0.3`, `^1.2.3-alpha.1` matches subsequent patch prereleases like `1.2.4-beta.1`, and build metadata distinguishes versions in `semver.compare` or `semver.eq`.

## Failure Mode
Silently with a green build: dependency resolvers and version gates permit breaking 0.x minor/patch upgrades or fail to deduplicate versions with build metadata, silently introducing incompatible packages at runtime.
csx.json
{"case":{"caseId":"case:sha256:6e7386acac62c63901aa3f381714d7c96a5499ee2055e3d96020cca4c0351b00","constraints":{"runtime":"node"},"contract":["assert ^0.2.3 rejects 0.3.0 because 0.x minor updates are breaking","assert ^0.0.3 locks to exact patch whereas ~0.0.3 allows patch updates","assert ^1.2.3-alpha.1 accepts 1.2.3-beta.1 but rejects 1.2.4-beta.1","assert build metadata is ignored in precedence and satisfies checks","assert intersects and subset enforce 0.x zero-major breaking boundaries"],"goal":"Evaluate 0.x caret and tilde boundaries, prerelease range matching rules, and build metadata equality in semver","kind":"HOW","packages":["pkg:npm/semver@7.8.5"],"schemaVersion":1,"symbols":["semver.satisfies","semver.subset","semver.intersects","semver.compare","semver.compareBuild","semver.maxSatisfying"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/semver@7.8.5"],"schemaVersion":1,"symbols":["semver.satisfies","semver.subset","semver.intersects","semver.compare","semver.compareBuild","semver.maxSatisfying"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-semver-range-satisfies",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-semver-range-satisfies",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "semver": "7.8.5"
      }
    },
    "node_modules/semver": {
      "version": "7.8.5",
      "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
      "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
      "license": "ISC",
      "bin": {
        "semver": "bin/semver.js"
      },
      "engines": {
        "node": ">=10"
      }
    }
  }
}
package.json
{
  "name": "npm-semver-range-satisfies",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "semver": "7.8.5"
  }
}
src/index.mjs
import semver from 'semver';

/**
 * Checks whether a version satisfies a caret (^) or tilde (~) range on 0.x versions.
 * In SemVer:
 * - For ^0.x.y (where x > 0), breaking changes are at minor level (e.g. ^0.2.3 := >=0.2.3 <0.3.0-0).
 * - For ^0.0.x, breaking changes are at patch level (e.g. ^0.0.3 := >=0.0.3 <0.0.4-0).
 * - For ~0.0.x, patch updates are permitted (e.g. ~0.0.3 := >=0.0.3 <0.1.0-0).
 */
export function satisfiesZeroVersion(version, range) {
  return semver.satisfies(version, range);
}

/**
 * Evaluates whether a prerelease version satisfies a range.
 * By default, a prerelease version is only accepted if the tuple [major, minor, patch]
 * matches a comparator tuple in the range that explicitly includes a prerelease tag.
 */
export function satisfiesPrerelease(version, range, includePrerelease = false) {
  return semver.satisfies(version, range, { includePrerelease });
}

/**
 * Compares two versions taking into account whether build metadata is ignored (standard)
 * or evaluated (compareBuild).
 */
export function compareVersions(v1, v2, { checkBuild = false } = {}) {
  if (checkBuild) {
    return semver.compareBuild(v1, v2);
  }
  return semver.compare(v1, v2);
}

/**
 * Performs lockfile resolution operations: range subset, intersection, and max satisfying version.
 */
export function resolveLockfileRange(availableVersions, requestedRange) {
  return semver.maxSatisfying(availableVersions, requestedRange);
}

export function isRangeSubset(subRange, parentRange) {
  return semver.subset(subRange, parentRange);
}

export function rangesIntersect(range1, range2) {
  return semver.intersects(range1, range2);
}
test/contract.mjs
import { strict as assert } from 'node:assert';
import {
  satisfiesZeroVersion,
  satisfiesPrerelease,
  compareVersions,
  resolveLockfileRange,
  isRangeSubset,
  rangesIntersect,
} from '../src/index.mjs';

// 1. Caret and Tilde behavior on 0.x versions
// ^0.2.3 allows patch updates but rejects minor bumps (breaking in 0.x)
assert.equal(satisfiesZeroVersion('0.2.4', '^0.2.3'), true);
assert.equal(satisfiesZeroVersion('0.3.0', '^0.2.3'), false);

// ^0.0.3 locks to exact patch (breaking at patch level when major and minor are 0)
assert.equal(satisfiesZeroVersion('0.0.4', '^0.0.3'), false);
assert.equal(satisfiesZeroVersion('0.0.3', '^0.0.3'), true);

// ~0.0.3 allows patch updates up to next minor (<0.1.0-0), unlike ^0.0.3
assert.equal(satisfiesZeroVersion('0.0.4', '~0.0.3'), true);
assert.equal(satisfiesZeroVersion('0.1.0', '~0.0.3'), false);

// 2. Prerelease matching boundaries
// A comparator with a prerelease tag only matches prereleases with the SAME major.minor.patch tuple
assert.equal(satisfiesPrerelease('1.2.3-beta.1', '^1.2.3-alpha.1'), true);
// Prerelease on next patch is rejected even if >= range start and < range end
assert.equal(satisfiesPrerelease('1.2.4-beta.1', '^1.2.3-alpha.1'), false);
// But the final release of the next patch is accepted
assert.equal(satisfiesPrerelease('1.2.4', '^1.2.3-alpha.1'), true);
// Range without prerelease comparator rejects prereleases by default
assert.equal(satisfiesPrerelease('1.2.3-alpha.1', '^1.2.0'), false);
// With includePrerelease flag, it is accepted
assert.equal(satisfiesPrerelease('1.2.3-alpha.1', '^1.2.0', true), true);

// 3. Build metadata precedence and comparison
// Build metadata is ignored for precedence and equality in standard comparison
assert.equal(compareVersions('1.2.3+build.1', '1.2.3+build.2'), 0);
assert.equal(satisfiesZeroVersion('1.2.3+build.99', '1.2.3+build.1'), true);
// Only compareBuild differentiates build metadata
assert.equal(compareVersions('1.2.3+build.1', '1.2.3+build.2', { checkBuild: true }), -1);

// 4. Lockfile resolution and range intersection
// Range subset within 0.x
assert.equal(isRangeSubset('^0.2.3', '^0.2.0'), true);
assert.equal(isRangeSubset('^0.3.0', '^0.2.0'), false);

// Intersect checks across 0.x boundaries
assert.equal(rangesIntersect('^0.2.0', '^0.2.5'), true);
assert.equal(rangesIntersect('^0.2.0', '^0.3.0'), false);
assert.equal(rangesIntersect('^0.0.1', '^0.0.2'), false);

// Resolution selects highest matching version bounded by 0.x breaking rules
const candidateVersions = ['0.2.3', '0.2.9', '0.3.0', '1.0.0'];
assert.equal(resolveLockfileRange(candidateVersions, '^0.2.0'), '0.2.9');

console.log('CONTRACT PASS: semver 0.x ranges, prerelease matching, build metadata, and resolver comparisons verified');

Ursprungs-Seeder

anonymous