@std/semver
Обзор
Парсер семантических версий.
Напрямую адаптирован из semver.
import {
parse,
parseRange,
greaterThan,
lessThan,
format
} from "@std/semver";
import { assertEquals } from "@std/assert";
const semver = parse("1.2.3");
assertEquals(semver, {
major: 1,
minor: 2,
patch: 3,
prerelease: [],
build: []
});
assertEquals(format(semver), "1.2.3");
const range = parseRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3");
const s0 = parse("1.2.3");
const s1 = parse("9.8.7");
assertEquals(greaterThan(s0, s1), false);
assertEquals(lessThan(s0, s1), true);
Версии
«Версия» описывается спецификацией v2.0.0, опубликованной по адресу https://semver.org.
Начальный символ "=" или "v" удаляется и игнорируется.
Формат
Семантические версии можно форматировать в виде строк; по умолчанию они форматируются как full. Ниже приведена диаграмма с различными вариантами форматирования.
full
┌───┴───┐
release │
┌───┴───┐ │
primary │ │
┌─┴─┐ │ │
1.2.3-pre.1+b.1
│ │ │ └─┬─┘ └┬┘
│ │ │ │ └── build
│ │ │ └─────── pre
│ │ └─────────── patch
│ └───────────── minor
└─────────────── major
Диапазоны
Range версий — это набор Comparator, задающих версии, которые удовлетворяют диапазону.
Comparator состоит из Operator и SemVer. Набор примитивных operators включает:
-
<меньше -
<=меньше или равно -
>больше -
>=больше или равно -
=равно. Если оператор не указан, предполагается равенство, поэтому этот оператор необязателен, но МОЖЕТ быть указан.
Например, компаратор >=1.2.7 будет соответствовать версиям 1.2.7, 1.2.8, 2.5.3 и 1.3.9, но не версиям 1.2.6 или 1.1.0.
Компараторы можно объединять пробелами, образуя comparator set, которому удовлетворяет пересечение всех входящих в него компараторов.
Диапазон состоит из одного или нескольких наборов компараторов, объединённых с помощью ||. Версия соответствует диапазону тогда и только тогда, когда версия удовлетворяет каждому компаратору хотя бы в одном из наборов компараторов, разделённых ||.
Например, диапазону >=1.2.7 <1.3.0 будут соответствовать версии 1.2.7, 1.2.8 и 1.2.99, но не версии 1.2.6, 1.3.0 или 1.1.0.
Диапазону 1.2.7 || >=1.2.9 <2.0.0 будут соответствовать версии 1.2.7, 1.2.9 и 1.4.6, но не версии 1.2.8 или 2.0.0.
Теги предварительного выпуска
Если у версии есть тег предварительного выпуска (например, 1.2.3-alpha.3), то она будет удовлетворять наборам компараторов только в том случае, если хотя бы один компаратор с таким же кортежем [major, minor, patch] также имеет тег предварительного выпуска.
Например, диапазону >1.2.3-alpha.3 будет соответствовать версия 1.2.3-alpha.7, но ему не будет удовлетворять 3.4.5-alpha.9, хотя согласно правилам сортировки SemVer 3.4.5-alpha.9 технически «больше», чем 1.2.3-alpha.3. Диапазон версий принимает теги предварительного выпуска только для версии 1.2.3. Версия 3.4.5 будет удовлетворять диапазону, поскольку у неё нет флага предварительного выпуска, а 3.4.5 больше, чем 1.2.3-alpha.7.
У такого поведения две причины. Во-первых, версии предварительного выпуска часто обновляются очень быстро и содержат множество несовместимых изменений, которые (по замыслу автора) ещё не предназначены для публичного использования. Поэтому по умолчанию они исключаются из семантики сопоставления диапазонов.
Во-вторых, пользователь, решивший использовать версию предварительного выпуска, явно указал намерение использовать именно этот набор альфа-, бета- или rc-версий. Добавляя тег предварительного выпуска в диапазон, пользователь показывает, что осознаёт связанный с этим риск. Однако нельзя считать, что он согласен принять аналогичный риск и для следующего набора версий предварительного выпуска.
Идентификаторы предварительного выпуска
Метод increment принимает дополнительный строковый аргумент identifier, который добавляет значение строки в качестве идентификатора предварительного выпуска:
import { increment, parse } from "@std/semver";
import { assertEquals } from "@std/assert";
assertEquals(increment(parse("1.2.3"), "prerelease", { prerelease: "alpha" }), parse("1.2.4-alpha.0"));
Метаданные сборки
Метаданные сборки — это строка из букв и цифр, разделённая .. При разборе версии они сохраняются в поле build: string[] экземпляра SemVer. При увеличении версии предусмотрен дополнительный параметр, позволяющий задать метаданные сборки для экземпляра SemVer.
Расширенный синтаксис диапазонов
Расширенный синтаксис диапазонов детерминированным образом преобразуется в примитивные компараторы.
Расширенные диапазоны можно комбинировать так же, как примитивные компараторы, используя пробелы или ||.
Диапазоны с дефисом X.Y.Z - A.B.C
Задаёт включительный диапазон.
-
1.2.3 - 2.3.4:=>=1.2.3 <=2.3.4
Если в качестве первой версии включительного диапазона указана неполная версия, недостающие части заменяются нулями.
-
1.2 - 2.3.4:=>=1.2.0 <=2.3.4
Если в качестве второй версии включительного диапазона указана неполная версия, принимаются все версии, начинающиеся с указанных частей кортежа, но не версии, значения которых превышают указанные части кортежа.
-
1.2.3 - 2.3:=>=1.2.3 <2.4.0 -
1.2.3 - 2:=>=1.2.3 <3.0.0
Диапазоны X 1.2.x 1.X 1.2.* *
Любой из символов X, x или * можно использовать вместо одного из числовых значений в кортеже [major, minor, patch].
-
*:=>=0.0.0(подходит любая версия) -
1.x:=>=1.0.0 <2.0.0(совпадает основная версия) -
1.2.x:=>=1.2.0 <1.3.0(совпадают основная и дополнительная версии)
Неполный диапазон версий рассматривается как диапазон X, поэтому специальный символ фактически необязателен.
-
""(пустая строка) :=*:=>=0.0.0 -
1:=1.x.x:=>=1.0.0 <2.0.0 -
1.2:=1.2.x:=>=1.2.0 <1.3.0
Диапазоны с тильдой ~1.2.3 ~1.2 ~1
Допускает изменения на уровне исправлений, если в компараторе указана дополнительная версия. Если она не указана, допускает изменения на уровне дополнительных версий.
-
~1.2.3:=>=1.2.3 <1.(2+1).0:=>=1.2.3 <1.3.0 -
~1.2:=>=1.2.0 <1.(2+1).0:=>=1.2.0 <1.3.0(то же, что1.2.x) -
~1:=>=1.0.0 <(1+1).0.0:=>=1.0.0 <2.0.0(то же, что1.x) -
~0.2.3:=>=0.2.3 <0.(2+1).0:=>=0.2.3 <0.3.0 -
~0.2:=>=0.2.0 <0.(2+1).0:=>=0.2.0 <0.3.0(то же, что0.2.x) -
~0:=>=0.0.0 <(0+1).0.0:=>=0.0.0 <1.0.0(то же, что0.x) -
~1.2.3-beta.2:=>=1.2.3-beta.2 <1.3.0Обратите внимание: версии предварительного выпуска в версии1.2.3будут допущены, если они больше или равныbeta.2. Так,1.2.3-beta.4будет допущена, а1.2.4-beta.2— нет, поскольку это предварительный выпуск другого кортежа[major, minor, patch].
Диапазоны с кареткой ^1.2.3 ^0.2.5 ^0.0.4
Допускает изменения, не затрагивающие самый левый ненулевой элемент кортежа [major, minor, patch]. Иными словами, для версий 1.0.0 и выше допускаются обновления на уровне исправлений и дополнительных версий; для версий 0.X >=0.1.0 — обновления на уровне исправлений, а для версий 0.0.X обновления не допускаются.
Многие авторы считают версию 0.x такой, в которой именно x выступает основным индикатором «несовместимых изменений».
Диапазоны с кареткой идеально подходят для случаев, когда автор может вносить несовместимые изменения между выпусками 0.2.4 и 0.3.0, что является распространённой практикой. Однако предполагается, что между выпусками 0.2.4 и 0.2.5 несовместимых изменений не будет. Такие диапазоны допускают изменения, которые, согласно общепринятой практике, считаются аддитивными (но не нарушающими совместимость).
-
^1.2.3:=>=1.2.3 <2.0.0 -
^0.2.3:=>=0.2.3 <0.3.0 -
^0.0.3:=>=0.0.3 <0.0.4 -
^1.2.3-beta.2:=>=1.2.3-beta.2 <2.0.0Обратите внимание: версии предварительного выпуска в версии1.2.3будут допущены, если они больше или равныbeta.2. Так,1.2.3-beta.4будет допущена, а1.2.4-beta.2— нет, поскольку это предварительный выпуск другого кортежа[major, minor, patch]. -
^0.0.3-beta:=>=0.0.3-beta <0.0.4Обратите внимание: будут допущены только версии предварительного выпуска версии0.0.3, если они больше или равныbeta. Так,0.0.3-pr.2будет допущена.
При разборе диапазонов с кареткой отсутствующее значение patch преобразуется в число 0, но при этом допускается изменение в пределах этого значения, даже если и основная, и дополнительная версии равны 0.
-
^1.2.x:=>=1.2.0 <2.0.0 -
^0.0.x:=>=0.0.0 <0.1.0 -
^0.0:=>=0.0.0 <0.1.0
Отсутствующие значения minor и patch преобразуются в ноль, но при этом допускаются изменения в пределах этих значений, даже если основная версия равна нулю.
-
^1.x:=>=1.0.0 <2.0.0 -
^0.x:=>=0.0.0 <1.0.0
Грамматика диапазонов
Объединив всё это, получим грамматику диапазонов в форме Бэкуса — Наура, предназначенную для разработчиков парсеров:
range-set ::= range ( logical-or range ) *
logical-or ::= ( " " ) * "||" ( " " ) *
range ::= hyphen | simple ( " " simple ) * | ""
hyphen ::= partial " - " partial
simple ::= primitive | partial | tilde | caret
primitive ::= ( "<" | ">" | ">=" | "<=" | "=" ) partial
partial ::= xr ( "." xr ( "." xr qualifier ? )? )?
xr ::= "x" | "X" | "*" | nr
nr ::= "0" | ["1"-"9"] ( ["0"-"9"] ) *
tilde ::= "~" partial
caret ::= "^" partial
qualifier ::= ( "-" pre )? ( "+" build )?
pre ::= parts
build ::= parts
parts ::= part ( "." part ) *
part ::= nr | [-0-9A-Za-z]+
Обратите внимание: поскольку диапазоны могут быть несмежными, версия может быть не больше диапазона, не меньше диапазона и не удовлетворять диапазону! Например, в диапазоне 1.2 <1.2.9 || >2.0.0 будет разрыв от 1.2.9 до 2.0.0, поэтому версия 1.2.10 не будет больше диапазона (поскольку ему удовлетворяет 2.0.1, которая выше), не будет меньше диапазона (поскольку ему удовлетворяет 1.2.8, которая ниже) и также не будет удовлетворять диапазону.
Чтобы определить, удовлетворяет ли версия диапазону, используйте функцию satisfies.
Добавление в проект
deno add jsr:@std/semver
© 2018–2025 the Deno authors
Licensed under the MIT License.
https://docs.deno.com/runtime/reference/std/semver