UNPKG

@verdaccio/local-storage

Version:

Local storage implementation

225 lines (224 loc) 7.09 kB
const require_runtime = require("./_virtual/_rolldown/runtime.js"); const require_dir_utils = require("./dir-utils.js"); const require_local_fs = require("./local-fs.js"); const require_pkg_utils = require("./pkg-utils.js"); const require_token = require("./token.js"); let debug = require("debug"); debug = require_runtime.__toESM(debug); let fs = require("fs"); fs = require_runtime.__toESM(fs); let lodash = require("lodash"); lodash = require_runtime.__toESM(lodash); let mkdirp = require("mkdirp"); mkdirp = require_runtime.__toESM(mkdirp); let path = require("path"); path = require_runtime.__toESM(path); let _verdaccio_core = require("@verdaccio/core"); //#region src/local-database.ts var debug$1 = (0, debug.default)("verdaccio:plugin:local-storage:database"); var LocalDatabase = class extends require_token.default { path; logger; data; config; locked; constructor(config, logger) { super(config); this.config = config; this.path = this._dbGenPath(_verdaccio_core.fileUtils.Files.DatabaseName, config); this.logger = logger; this.locked = false; this.data = this._fetchLocalPackages(); this._sync(); } getSecret() { return Promise.resolve(this.data.secret); } setSecret(secret) { return new Promise((resolve) => { this.data.secret = secret; resolve(this._sync()); }); } add(name, cb) { if (this.data.list.indexOf(name) === -1) { this.data.list.push(name); debug$1("the private package %o has been added", name); cb(this._sync()); } else { debug$1("the private package %o was not added", name); cb(null); } } /** * Filter and only match those values that the query define. **/ async filterByQuery(results, query) { return results.filter((item) => { return item?.name?.match(query.text) !== null; }); } async getScore(_pkg) { return Promise.resolve({ final: 1, detail: { maintenance: 0, popularity: 1, quality: 1 } }); } _getCustomPackageLocalStorages() { const storages = /* @__PURE__ */ new Map(); const { packages } = this.config; if (packages) Object.keys(packages || {}).map((pkg) => { const { storage } = packages[pkg]; if (typeof storage === "string") { const storagePath = path.default.join(this.getStoragePath(), storage); debug$1("add custom storage for %s on %s", storage, storagePath); storages.set(storage, storagePath); } }); return storages; } async search(query) { const results = []; const storagePath = this.getStoragePath(); const storages = this._getCustomPackageLocalStorages(); const packagesOnStorage = await this.filterByQuery(await require_dir_utils.searchOnStorage(storagePath, storages), query); debug$1("packages found %o", packagesOnStorage.length); for (const storage of packagesOnStorage) { const isPrivate = this.data.list.includes(storage.name); const score = await this.getScore(storage); results.push({ package: storage, verdaccioPrivate: isPrivate, verdaccioPkgCached: !isPrivate, score }); } return results; } remove(name, cb) { this.get((err, data) => { if (err) { cb(_verdaccio_core.errorUtils.getInternalError("error remove private package")); this.logger.error({ err }, "remove the private package has failed @{err}"); debug$1("error on remove package %o", name); } const pkgName = data.indexOf(name); if (pkgName !== -1) { this.data.list.splice(pkgName, 1); debug$1("remove package %o has been removed", name); } cb(this._sync()); }); } /** * Return all database elements. * @return {Array} */ get(cb) { const list = this.data.list; const totalItems = this.data.list.length; cb(null, list); debug$1("get full list of packages (%o) has been fetched", totalItems); } getPackageStorage(packageName) { const packageAccess = this.config.getMatchedPackagesSpec(packageName); const packagePath = this._getLocalStoragePath(packageAccess ? packageAccess.storage : void 0); debug$1("storage path selected: ", packagePath); if (lodash.default.isString(packagePath) === false) { debug$1("the package %o has no storage defined ", packageName); return; } const packageStoragePath = path.default.join(path.default.resolve(path.default.dirname(this.config.self_path || ""), packagePath), packageName); debug$1("storage absolute path: ", packageStoragePath); return new require_local_fs.default(packageStoragePath, this.logger); } clean() { this._sync(); } getTime(time, mtime) { return time ? time : mtime; } /** * Syncronize {create} database whether does not exist. * @return {Error|*} */ _sync() { debug$1("sync database started"); if (this.locked) { this.logger.error("Database is locked, please check error message printed during startup to prevent data loss."); return /* @__PURE__ */ new Error("Verdaccio database is locked, please contact your administrator to checkout logs during verdaccio startup."); } try { const folderName = path.default.dirname(this.path); mkdirp.default.sync(folderName); debug$1("sync folder %o created succeed", folderName); } catch (err) { debug$1("sync create folder has failed with error: %o", err); return null; } try { fs.default.writeFileSync(this.path, JSON.stringify(this.data)); debug$1("sync write succeed"); return null; } catch (err) { debug$1("sync failed %o", err); return err; } } getBaseConfigPath() { return path.default.dirname(this.config.configPath); } /** * The field storage could be absolute or relative. * If relative, it will be resolved against the config path. * If absolute, it will be returned as is. **/ getStoragePath() { const { storage } = this.config; if (typeof storage !== "string") throw new TypeError("storage field is mandatory"); const storagePath = path.default.isAbsolute(storage) ? storage : path.default.normalize(path.default.join(this.getBaseConfigPath(), storage)); debug$1("storage path %o", storagePath); return storagePath; } /** * Verify the right local storage location. * @param {String} path * @return {String} * @private */ _getLocalStoragePath(storage) { const globalConfigStorage = this.config ? this.config.storage : void 0; if (lodash.default.isNil(globalConfigStorage)) throw new Error("global storage is required for this plugin"); else { if (lodash.default.isNil(storage) === false && lodash.default.isString(storage)) return path.default.join(globalConfigStorage, storage); return globalConfigStorage; } } /** * Fetch local packages. * @private * @return {Object} */ _fetchLocalPackages() { const emptyDatabase = { list: [], secret: "" }; try { return require_pkg_utils.loadPrivatePackages(this.path, this.logger); } catch (err) { if (err.code !== "ENOENT") { this.locked = true; this.logger.error("Failed to read package database file, please check the error printed below:\n", `File Path: ${this.path}\n\n ${err.message}`); } return emptyDatabase; } } }; //#endregion exports.default = LocalDatabase; //# sourceMappingURL=local-database.js.map