mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Initial
This commit is contained in:
parent
2676170b61
commit
4564b7f607
19 changed files with 1057 additions and 28 deletions
|
|
@ -0,0 +1,125 @@
|
|||
import { parsePipPackageFromUrl } from "./parsePipPackageUrl.js";
|
||||
|
||||
/**
|
||||
* @param {any} file
|
||||
* @param {string} metadataUrl
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export function getPackageVersionFromMetadataFile(file, metadataUrl) {
|
||||
const href = typeof file?.url === "string" ? file.url : undefined;
|
||||
const filename = typeof file?.filename === "string" ? file.filename : undefined;
|
||||
|
||||
if (href) {
|
||||
const resolvedHref = new URL(href, metadataUrl).toString();
|
||||
return parsePipPackageFromUrl(
|
||||
resolvedHref,
|
||||
new URL(resolvedHref).host
|
||||
).version;
|
||||
}
|
||||
|
||||
if (filename) {
|
||||
return parsePipPackageFromUrl(
|
||||
new URL(filename, metadataUrl).toString(),
|
||||
new URL(metadataUrl).host
|
||||
).version;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} json
|
||||
* @param {string} metadataUrl
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function getAvailableVersionsFromJson(json, metadataUrl) {
|
||||
if (json.releases && typeof json.releases === "object") {
|
||||
return Object.keys(json.releases);
|
||||
}
|
||||
|
||||
if (Array.isArray(json.files)) {
|
||||
return [
|
||||
...new Set(
|
||||
json.files
|
||||
.map((/** @type {any} */ file) =>
|
||||
getPackageVersionFromMetadataFile(file, metadataUrl)
|
||||
)
|
||||
.filter((/** @type {string | undefined} */ version) =>
|
||||
typeof version === "string"
|
||||
)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} versions
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export function calculateLatestVersion(versions) {
|
||||
const stableVersions = versions.filter((version) => !isPrerelease(version));
|
||||
if (stableVersions.length > 0) {
|
||||
return stableVersions.sort(comparePep440ishVersions).at(-1);
|
||||
}
|
||||
|
||||
return versions.sort(comparePep440ishVersions).at(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} left
|
||||
* @param {string} right
|
||||
* @returns {number}
|
||||
*/
|
||||
function comparePep440ishVersions(left, right) {
|
||||
const leftParts = tokenizeVersion(left);
|
||||
const rightParts = tokenizeVersion(right);
|
||||
const maxLength = Math.max(leftParts.length, rightParts.length);
|
||||
|
||||
for (let index = 0; index < maxLength; index += 1) {
|
||||
const leftPart = leftParts[index];
|
||||
const rightPart = rightParts[index];
|
||||
|
||||
if (leftPart === undefined) return -1;
|
||||
if (rightPart === undefined) return 1;
|
||||
|
||||
if (leftPart === rightPart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const leftNumeric = typeof leftPart === "number";
|
||||
const rightNumeric = typeof rightPart === "number";
|
||||
|
||||
if (leftNumeric && rightNumeric) {
|
||||
return leftPart - rightPart;
|
||||
}
|
||||
|
||||
if (leftNumeric) return 1;
|
||||
if (rightNumeric) return -1;
|
||||
|
||||
return String(leftPart).localeCompare(String(rightPart));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} version
|
||||
* @returns {(string | number)[]}
|
||||
*/
|
||||
function tokenizeVersion(version) {
|
||||
return version
|
||||
.toLowerCase()
|
||||
.split(/[^a-z0-9]+/)
|
||||
.flatMap((part) => part.match(/[a-z]+|\d+/g) || [])
|
||||
.map((part) => (/^\d+$/.test(part) ? Number(part) : part));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} version
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isPrerelease(version) {
|
||||
return /(?:^|[.\-_])(a|b|rc|dev)\d*/i.test(version);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue