@shockpkg/core
Version:
shockpkg core
534 lines (425 loc) • 10.8 kB
JavaScript
import _initializerDefineProperty from "@babel/runtime/helpers/initializerDefineProperty.js";
import _applyDecoratedDescriptor from "@babel/runtime/helpers/applyDecoratedDescriptor.js";
import _initializerWarningHelper from "@babel/runtime/helpers/initializerWarningHelper.js";
var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _class, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _class2, _temp;
import fse from 'fs-extra';
import { property } from "./decorators.mjs";
import { Package } from "./package.mjs";
/**
* Packages constructor.
*
* @param path The path to the packages file.
*/
export let Packages = (_dec = property(false), _dec2 = property(false), _dec3 = property(false), _dec4 = property(false), _dec5 = property(false), _dec6 = property(false), (_class = (_temp = _class2 = class Packages extends Object {
/**
* Packages data.
*/
/**
* Packages array.
*/
/**
* Packages mapped by name.
*/
/**
* Packages mapped by sha256.
*/
/**
* Packages mapped by unique.
*/
/**
* The path to the packages file.
*/
/**
* Format version.
*/
constructor(path) {
super();
_initializerDefineProperty(this, "_packagesList", _descriptor, this);
_initializerDefineProperty(this, "_packages", _descriptor2, this);
_initializerDefineProperty(this, "_packagesByName", _descriptor3, this);
_initializerDefineProperty(this, "_packagesBySha256", _descriptor4, this);
_initializerDefineProperty(this, "_packagesByUnique", _descriptor5, this);
_initializerDefineProperty(this, "_path", _descriptor6, this);
this._path = path;
}
/**
* Get path of the packages file.
*
* @returns The path.
*/
get path() {
return this._path;
}
/**
* Get if packages loaded.
*
* @returns Is loaded.
*/
get loaded() {
return !!this._packagesList;
}
/**
* Update packages.
*
* @param data Encoded data.
* @returns Update report.
*/
update(data) {
// Map out current list if any.
const map = new Map();
for (const pkg of this.itter()) {
const {
name,
file,
size,
sha256
} = pkg;
map.set(name, {
name,
file,
size,
sha256
});
} // Actually set the data.
this._setPackagesList(this._parseData(data)); // List out the changes of significance.
const updated = [];
const added = [];
const removed = [];
for (const pkg of this.itter()) {
const {
name,
file,
size,
sha256
} = pkg;
const obj = {
name,
file,
size,
sha256
};
const before = map.get(name) || null;
map.delete(name);
if (!before) {
added.push(obj);
continue;
}
if (before.sha256 !== sha256 || before.size !== size || before.file !== file) {
updated.push(obj);
}
}
for (const [, obj] of map) {
removed.push(obj);
}
return {
updated,
added,
removed
};
}
/**
* Assert loaded.
*/
assertLoaded() {
if (!this.loaded) {
throw new Error('Packages list not loaded');
}
}
/**
* Check if the file path exists.
*
* @returns Does exist.
*/
async exists() {
return fse.pathExists(this.path);
}
/**
* Read the file path.
*/
async read() {
const data = await fse.readJson(this.path);
this._setPackagesList(this._castData(data));
}
/**
* Write packages to the file path.
*/
async write() {
if (!this._packagesList) {
throw new Error('Cannot write unloaded list');
}
await fse.writeJson(this.path, this._packagesList, {
spaces: '\t'
});
}
/**
* Read the file path if the file exists.
*
* @returns Did exist.
*/
async readIfExists() {
if (await this.exists()) {
await this.read();
return true;
}
return false;
}
/**
* Itterate over the packages.
*/
*itter() {
const packages = this._packages;
for (const entry of packages) {
// If the set changes, break loop.
if (packages !== this._packages) {
break;
}
yield entry;
}
}
/**
* Check if package is in this collection.
*
* @param pkg Package instance.
* @returns If the package instance is present.
*/
has(pkg) {
return this._packages.has(pkg);
}
/**
* Assert the package is in this collection.
*
* @param pkg Package instance.
*/
assertHas(pkg) {
if (!this.has(pkg)) {
throw new Error('Package not in collection');
}
}
/**
* Get package by the unique name.
*
* @param name Package name.
* @returns The package or null.
*/
byName(name) {
return this._packagesByName.get(name) || null;
}
/**
* Get package by the sha256 hash.
*
* @param sha256 Package sha256.
* @returns The package or null.
*/
bySha256(sha256) {
return this._packagesBySha256.get(sha256) || null;
}
/**
* Get package by the unique value.
*
* @param unique Package unique.
* @returns The package or null.
*/
byUnique(unique) {
return this._packagesByUnique.get(unique) || null;
}
/**
* Create a package instance.
*
* @param info Package info.
* @returns Package instance.
*/
_createPackage(info) {
return new Package(info);
}
/**
* Set the packages list.
*
* @param packagesList Parsed list.
*/
_setPackagesList(packagesList) {
this._validateFormat(packagesList.format);
const parsed = this._parsePackages(packagesList.packages);
const packages = this._listPackages(parsed); // Map out the names and hashes.
const byName = this._packagesMapName(packages);
const bySha256 = this._packagesMapSha256(packages);
const byUnique = this._packagesMapUnique(packages); // If all parsed successfully, set properties.
this._packagesList = packagesList;
this._packages = packages;
this._packagesByName = byName;
this._packagesBySha256 = bySha256;
this._packagesByUnique = byUnique;
}
/**
* Validate format version string.
*
* @param format The format version string.
*/
_validateFormat(format) {
const Constructor = this.constructor;
const version = Constructor.FORMAT.split('.').map(Number);
const parts = format.split('.').map(Number);
if (parts.length !== 2) {
throw new Error(`Invalid format version value: ${format}`);
}
if (!(parts[0] === version[0])) {
throw new Error(`Invalid format version major: ${format}`);
}
if (!(parts[1] >= version[1])) {
throw new Error(`Invalid format version minor: ${format}`);
}
}
/**
* Parse the packages list.
*
* @param packages Packages list.
* @returns Parsed list.
*/
_parsePackages(packages) {
return packages.map(info => this._createPackage(info));
}
/**
* List all packages deep.
*
* @param packages A list of packages.
* @returns A set of all packages and their children.
*/
_listPackages(packages) {
const r = new Set();
const itter = [...packages]; // tslint:disable-next-line: no-constant-condition
// eslint-disable-next-line no-constant-condition
while (true) {
const entry = itter.shift();
if (!entry) {
break;
}
r.add(entry);
const chilren = entry.packages;
if (chilren) {
itter.unshift(...chilren);
}
}
return r;
}
/**
* Map out package list by name.
* Throws on any duplicates.
*
* @param packages Packages list.
* @returns Map from package name to package.
*/
_packagesMapName(packages) {
const r = new Map();
for (const entry of packages) {
const {
name
} = entry;
if (r.has(name)) {
throw new Error(`Duplicate package name: ${name}`);
}
r.set(name, entry);
}
return r;
}
/**
* Map out package list by sha256.
* Throws on any duplicates.
*
* @param packages Packages list.
* @returns Map from package sha256 to package.
*/
_packagesMapSha256(packages) {
const r = new Map();
for (const entry of packages) {
const {
sha256
} = entry;
if (r.has(sha256)) {
throw new Error(`Duplicate package sha256: ${sha256}`);
}
r.set(sha256, entry);
}
return r;
}
/**
* Map out package list by unique.
* Throws on any duplicates.
*
* @param packages Packages list.
* @returns Map from package unique to package.
*/
_packagesMapUnique(packages) {
const r = new Map();
for (const entry of packages) {
for (const unique of [entry.name, entry.sha256]) {
if (r.has(unique)) {
throw new Error(`Duplicate package unique: ${unique}`);
}
r.set(unique, entry);
}
}
return r;
}
/**
* Parse and cast the encoded data.
*
* @param data Encoded data.
* @returns Parsed and cast data.
*/
_parseData(data) {
const parsed = JSON.parse(data);
return this._castData(parsed);
}
/**
* Cast the parsed data.
*
* @param packages Parsed data.
* @returns Cast data.
*/
_castData(packages) {
if (!packages || typeof packages !== 'object' || typeof packages.format !== 'string' || !Array.isArray(packages.packages)) {
throw new Error('Failed to validate packages');
}
return packages;
}
}, _class2.FORMAT = '1.0', _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "_packagesList", [_dec], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return null;
}
}), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "_packages", [_dec2], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return new Set();
}
}), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "_packagesByName", [_dec3], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return new Map();
}
}), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "_packagesBySha256", [_dec4], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return new Map();
}
}), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "_packagesByUnique", [_dec5], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return new Map();
}
}), _descriptor6 = _applyDecoratedDescriptor(_class.prototype, "_path", [_dec6], {
configurable: true,
enumerable: true,
writable: true,
initializer: null
})), _class));
//# sourceMappingURL=packages.mjs.map