UNPKG

@shockpkg/core

Version:
534 lines (425 loc) 10.8 kB
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