@open-audio-stack/core
Version:
Open-source audio plugin management software
90 lines (89 loc) • 3.37 kB
JavaScript
import * as semver from 'semver';
import { packageErrors, packageIsVerified, packageRecommendations } from '../helpers/package.js';
import { isValidSlug } from '../helpers/utils.js';
import { Base } from './Base.js';
export class Package extends Base {
reports;
slug;
version;
versions;
constructor(slug, versions) {
super();
if (!isValidSlug(slug))
this.log('Invalid package slug', slug);
this.reports = new Map();
this.slug = slug;
this.versions = versions ? new Map(Object.entries(versions)) : new Map();
this.version = this.latestVersion();
}
addVersion(num, version) {
// For now allow package versions to be overwritten.
// if (this.versions.has(num)) return this.log(`Package ${version.name} version ${num} already exists`);
const errors = packageErrors(version);
const recs = packageRecommendations(version);
const report = {
...(errors.length > 0 && { errors }),
...(recs.length > 0 && { recs }),
};
if (Object.keys(report).length > 0)
this.reports.set(num, report);
if (errors.length > 0)
throw new Error(`Package ${version.name} version ${num} has validation errors: ${JSON.stringify(errors)}`);
version.verified = packageIsVerified(this.slug, version);
this.versions.set(num, version);
this.version = this.latestVersion();
}
removeVersion(num) {
if (!this.versions.has(num))
return;
this.versions.delete(num);
this.version = this.latestVersion();
}
getReport() {
return Object.fromEntries(this.reports);
}
outputReport() {
const reports = this.getReport();
for (const [ver, report] of Object.entries(reports)) {
this.logReport(`${this.slug}/${ver}`, report.errors, report.recs);
}
}
getVersion(num) {
return this.versions.get(num);
}
getVersionLatest() {
return this.versions.get(this.latestVersion());
}
getVersionOrLatest(num) {
if (num) {
const pkgVersion = this.getVersion(num);
if (pkgVersion)
return pkgVersion;
}
return this.getVersionLatest();
}
latestVersion() {
return Array.from(this.versions.keys()).sort(semver.rcompare)[0] || '0.0.0';
}
// Rollup across every published version's own downloads rollup (itself a sum of that
// version's files) - i.e. total downloads for this package, all-time. Pure aggregation over
// whatever `downloads` values are already present; does not fetch anything itself.
getTotalDownloads() {
let total = 0;
for (const [, pkgVersion] of this.versions) {
total += pkgVersion.downloads || 0;
}
return total;
}
toJSON() {
const totalDownloads = this.getTotalDownloads();
return {
slug: this.slug,
version: this.version,
versions: Object.fromEntries(this.versions),
// Omit rather than write `downloads: 0` - keeps generated JSON smaller, and "0" wouldn't
// distinguish "genuinely zero downloads" from "not fetched yet" anyway.
...(totalDownloads > 0 && { downloads: totalDownloads }),
};
}
}