jsii-pacmak
Version:
A code generation framework for jsii backend languages
222 lines • 9.95 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.toReleaseVersion = exports.toPythonVersionRange = exports.toNuGetVersionRange = exports.toMavenVersionRange = void 0;
const semver_1 = require("semver");
const util_1 = require("util");
const _1 = require(".");
/**
* Converts a SemVer range expression to a Maven version range expression.
*
* @param semverRange the SemVer range expression to convert.
* @param suffix the suffix to add to versions in the range.
*
* @see https://cwiki.apache.org/confluence/display/MAVENOLD/Dependency+Mediation+and+Conflict+Resolution
*/
function toMavenVersionRange(semverRange, suffix) {
return toBracketNotation(semverRange, suffix, {
semver: false,
target: _1.TargetName.JAVA,
});
}
exports.toMavenVersionRange = toMavenVersionRange;
/**
* Converts a SemVer range expression to a NuGet version range expression.
*
* @param semverRange the SemVer range expression to convert.
*
* @see https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges-and-wildcards
*/
function toNuGetVersionRange(semverRange) {
return toBracketNotation(semverRange, undefined, {
semver: false,
target: _1.TargetName.DOTNET,
});
}
exports.toNuGetVersionRange = toNuGetVersionRange;
/**
* Converts a SemVer range expression to a Python setuptools compatible version
* constraint expression.
*
* @param semverRange the SemVer range expression to convert.
*/
function toPythonVersionRange(semverRange) {
const range = new semver_1.Range(semverRange);
return range.set
.map((set) => set
.map((comp) => {
const versionId = toReleaseVersion(comp.semver.raw?.replace(/-0$/, '') ?? '0.0.0', _1.TargetName.PYTHON);
switch (comp.operator) {
case '':
// With ^0.0.0, somehow we get a left entry with an empty operator and value, we'll fix this up
return comp.value === '' ? '>=0.0.0' : `==${versionId}`;
case '=':
return `==${versionId}`;
default:
// >, >=, <, <= are all valid expressions
return `${comp.operator}${versionId}`;
}
})
.join(', '))
.join(', ');
}
exports.toPythonVersionRange = toPythonVersionRange;
/**
* Converts an original version number from the NPM convention to the target
* language's convention for expressing the same. For versions that do not
* include a prerelease identifier, this always returns the assembly version
* unmodified.
*
* @param assemblyVersion the assembly version being released
* @param target the target language for which the version is destined
*
* @returns the version that should be serialized
*/
function toReleaseVersion(assemblyVersion, target) {
const version = (0, semver_1.parse)(assemblyVersion);
if (version == null) {
throw new Error(`Unable to parse the provided assembly version: "${assemblyVersion}"`);
}
if (version.prerelease.length === 0) {
return assemblyVersion;
}
switch (target) {
case _1.TargetName.PYTHON:
const baseVersion = `${version.major}.${version.minor}.${version.patch}`;
// Python supports a limited set of identifiers... And we have a mapping table...
// https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning
const releaseLabels = {
alpha: 'a',
beta: 'b',
rc: 'rc',
post: 'post',
dev: 'dev',
pre: 'pre',
};
const validationErrors = [];
// Ensure that prerelease composed entirely of [label, sequence] pairs
version.prerelease.forEach((elem, idx, arr) => {
const next = arr[idx + 1];
if (typeof elem === 'string') {
if (!Object.keys(releaseLabels).includes(elem)) {
validationErrors.push(`Label ${elem} is not one of ${Object.keys(releaseLabels).join(',')}`);
}
if (next === undefined || !Number.isInteger(next)) {
validationErrors.push(`Label ${elem} must be followed by a positive integer`);
}
}
});
if (validationErrors.length > 0) {
throw new Error(`Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${(0, util_1.inspect)(version.prerelease)}. The format should be 'X.Y.Z-[label.sequence][.post.sequence][.(dev|pre).sequence]', where sequence is a positive integer and label is one of ${(0, util_1.inspect)(Object.keys(releaseLabels))}. Validation errors encountered: ${validationErrors.join(', ')}`);
}
// PEP440 supports multiple labels in a given version, so
// we should attempt to identify and map as many labels as
// possible from the given prerelease input
// e.g. 1.2.3-rc.123.dev.456.post.789 => 1.2.3.rc123.dev456.post789
const postIdx = version.prerelease.findIndex((v) => v.toString() === 'post');
const devIdx = version.prerelease.findIndex((v) => ['dev', 'pre'].includes(v.toString()));
const preReleaseIdx = version.prerelease.findIndex((v) => ['alpha', 'beta', 'rc'].includes(v.toString()));
const prereleaseVersion = [
preReleaseIdx > -1
? `${releaseLabels[version.prerelease[preReleaseIdx]]}${version.prerelease[preReleaseIdx + 1] ?? 0}`
: undefined,
postIdx > -1
? `post${version.prerelease[postIdx + 1] ?? 0}`
: undefined,
devIdx > -1 ? `dev${version.prerelease[devIdx + 1] ?? 0}` : undefined,
]
.filter((v) => v)
.join('.');
return version.build.length > 0
? `${baseVersion}.${prereleaseVersion}+${version.build.join('.')}`
: `${baseVersion}.${prereleaseVersion}`;
case _1.TargetName.DOTNET:
case _1.TargetName.GO:
case _1.TargetName.JAVA:
case _1.TargetName.JAVASCRIPT:
// Not touching - the NPM version number should be usable as-is
break;
}
return assemblyVersion;
}
exports.toReleaseVersion = toReleaseVersion;
/**
* Converts a semantic version range to the kind of bracket notation used by
* Maven and NuGet. For example, this turns `^1.2.3` into `[1.2.3,2.0.0)`.
*
* @param semverRange The semantic version range to be converted.
* @param suffix A version suffix to apply to versions in the resulting expression.
* @param semver Whether the target supports full semantic versioning (including
* `-0` as the lowest possible prerelease identifier)
*
* @returns a bracket-notation version range.
*/
function toBracketNotation(semverRange, suffix, { semver = true, target = _1.TargetName.JAVASCRIPT, } = {}) {
if (semverRange === '*' || semverRange === '^0.0.0') {
semverRange = '>=0.0.0';
}
const range = new semver_1.Range(semverRange);
return range.set
.map((set) => {
if (set.length === 1) {
const version = set[0].semver.raw;
if (!version && range.raw === '>=0.0.0') {
// Case where version is '*'
return `[0.0.0,)`;
}
switch (set[0].operator || '=') {
// "[version]" => means exactly version
case '=':
return `[${addSuffix(version)}]`;
// "(version,]" => means greater than version
case '>':
return `(${addSuffix(version)},)`;
// "[version,]" => means greater than or equal to that version
case '>=':
return `[${addSuffix(version)},)`;
// "[,version)" => means less than version
case '<':
return `(,${addSuffix(version, !semver)})`;
// "[,version]" => means less than or equal to version
case '<=':
return `(,${addSuffix(version)}]`;
}
}
else if (set.length === 2) {
const nugetRange = toBracketRange(set[0], set[1]);
if (nugetRange) {
return nugetRange;
}
}
throw new Error(`Unsupported SemVer range set in ${semverRange}: ${set
.map((comp) => comp.value)
.join(', ')}`);
})
.join(', ');
function toBracketRange(left, right) {
if (left.operator.startsWith('<') && right.operator.startsWith('>')) {
// Order isn't ideal, swap around..
[left, right] = [right, left];
}
// With ^0.0.0, somehow we get a left entry with an empty operator and value, we'll fix this up
if (left.operator === '' && left.value === '') {
left = new semver_1.Comparator('>=0.0.0', left.options);
}
if (!left.operator.startsWith('>') || !right.operator.startsWith('<')) {
// We only support ranges defined like "> (or >=) left, < (or <=) right"
return undefined;
}
const leftBrace = left.operator.endsWith('=') ? '[' : '(';
const rightBrace = right.operator.endsWith('=') ? ']' : ')';
return `${leftBrace}${addSuffix(left.semver.raw)},${addSuffix(right.semver.raw, right.operator === '<' && !semver)}${rightBrace}`;
}
function addSuffix(str, trimDashZero = false) {
if (!str) {
return '';
}
if (trimDashZero) {
str = str.replace(/-0$/, '');
}
return suffix ? `${str}${suffix}` : toReleaseVersion(str, target);
}
}
//# sourceMappingURL=version-utils.js.map
;