UNPKG

live-plugin-manager

Version:

Install and uninstall any node package at runtime from npm registry

844 lines 35 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PluginManager = void 0; const fs = __importStar(require("./fileSystem")); const path = __importStar(require("path")); const NpmRegistryClient_1 = require("./NpmRegistryClient"); const PluginVm_1 = require("./PluginVm"); const lockFile = __importStar(require("lockfile")); const semver = __importStar(require("semver")); const debug_1 = __importDefault(require("debug")); const GithubRegistryClient_1 = require("./GithubRegistryClient"); const BitbucketRegistryClient_1 = require("./BitbucketRegistryClient"); const VersionManager_1 = require("./VersionManager"); const debug = (0, debug_1.default)("live-plugin-manager"); const BASE_NPM_URL = "https://registry.npmjs.org"; const cwd = process.cwd(); function createDefaultOptions() { return { cwd, npmRegistryUrl: BASE_NPM_URL, sandbox: {}, npmRegistryConfig: {}, npmInstallMode: "useCache", pluginsPath: path.join(cwd, "plugin_packages"), requireCoreModules: true, hostRequire: require, ignoredDependencies: [/^@types\//], staticDependencies: {}, lockWait: 120000, lockStale: 180000, }; } const NPM_LATEST_TAG = "latest"; class PluginManager { constructor(options) { this.installedPlugins = new Array(); this.sandboxTemplates = new Map(); if (options && !options.pluginsPath && options.cwd) { options.pluginsPath = path.join(options.cwd, "plugin_packages"); } this.options = Object.assign(Object.assign({}, createDefaultOptions()), (options || {})); this.versionManager = new VersionManager_1.VersionManager({ cwd: this.options.cwd, rootPath: this.options.versionsPath || path.join(this.options.pluginsPath, ".versions") }); this.vm = new PluginVm_1.PluginVm(this); this.npmRegistry = new NpmRegistryClient_1.NpmRegistryClient(this.options.npmRegistryUrl, this.options.npmRegistryConfig); this.githubRegistry = new GithubRegistryClient_1.GithubRegistryClient(this.options.githubAuthentication); this.bitbucketRegistry = new BitbucketRegistryClient_1.BitbucketRegistryClient(this.options.bitbucketAuthentication); } install(name, version) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installLockFree(name, version); } finally { yield this.syncUnlock(); } }); } /** * Install a package from npm * @param name name of the package * @param version version of the package, default to "latest" */ installFromNpm(name, version = NPM_LATEST_TAG) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installFromNpmLockFreeCache(name, version); } finally { yield this.syncUnlock(); } }); } /** * Install a package from a local folder * @param location package local folder location * @param options options, if options.force == true then package is always reinstalled without version checking */ installFromPath(location, options = {}) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installFromPathLockFree(location, options); } finally { yield this.syncUnlock(); } }); } installFromGithub(repository) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installFromGithubLockFree(repository); } finally { yield this.syncUnlock(); } }); } installFromBitbucket(repository) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installFromBitbucketLockFree(repository); } finally { yield this.syncUnlock(); } }); } /** * Install a package by specifiing code directly. If no version is specified it will be always reinstalled. * @param name plugin name * @param code code to be loaded, equivalent to index.js * @param version optional version, if omitted no version check is performed */ installFromCode(name, code, version) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { return yield this.installFromCodeLockFree(name, code, version); } finally { yield this.syncUnlock(); } }); } uninstall(name) { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { yield this.uninstallLockFree(name); const removed = yield this.versionManager.uninstallOrphans(this.installedPlugins); yield Promise.all(removed .map(pluginInfo => this.deleteAndUnloadPlugin(pluginInfo))); } finally { yield this.syncUnlock(); } }); } uninstallAll() { return __awaiter(this, void 0, void 0, function* () { yield fs.ensureDir(this.options.pluginsPath); yield this.syncLock(); try { // TODO First I should install dependents plugins?? for (const plugin of this.installedPlugins.slice().reverse()) { yield this.uninstallLockFree(plugin.name); } const removed = yield this.versionManager.uninstallOrphans(this.installedPlugins); yield Promise.all(removed .map(pluginInfo => this.deleteAndUnloadPlugin(pluginInfo))); } finally { yield this.syncUnlock(); } }); } list() { return this.installedPlugins.map((p) => p); } require(fullName) { const { pluginName, requiredPath } = this.vm.splitRequire(fullName); const info = this.getInfo(pluginName); if (!info) { throw new Error(`${pluginName} not installed`); } return this.load(info, requiredPath); } setSandboxTemplate(name, sandbox) { const info = this.getInfo(name); if (!info) { throw new Error(`${name} not installed`); } if (!sandbox) { this.sandboxTemplates.delete(info.name); return; } this.sandboxTemplates.set(info.name, sandbox); } getSandboxTemplate(name) { return this.sandboxTemplates.get(name); } alreadyInstalled(name, version, mode = "satisfies") { const installedInfo = this.getInfo(name); if (installedInfo) { if (!version) { return installedInfo; } if (semver.satisfies(installedInfo.version, version)) { return installedInfo; } else if (mode === "satisfiesOrGreater" && semver.gtr(installedInfo.version, version)) { return installedInfo; } } return undefined; } getInfo(name) { return this.installedPlugins.find((p) => p.name === name); } queryPackage(name, version) { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } version = this.validatePluginVersion(version); if (version && this.githubRegistry.isGithubRepo(version)) { return this.queryPackageFromGithub(version); } return this.queryPackageFromNpm(name, version); } queryPackageFromNpm(name, version = NPM_LATEST_TAG) { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } version = this.validatePluginVersion(version); return this.npmRegistry.get(name, version); } queryPackageFromGithub(repository) { return this.githubRegistry.get(repository); } runScript(code) { return this.vm.runScript(code); } uninstallLockFree(name) { return __awaiter(this, void 0, void 0, function* () { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } if (debug.enabled) { debug(`Uninstalling ${name}...`); } const info = this.getInfo(name); if (!info) { if (debug.enabled) { debug(`${name} not installed`); } return; } yield this.deleteAndUnloadPlugin(info); }); } installLockFree(name, version) { return __awaiter(this, void 0, void 0, function* () { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } version = this.validatePluginVersion(version); if (version && this.githubRegistry.isGithubRepo(version)) { return this.installFromGithubLockFree(version); } return this.installFromNpmLockFreeCache(name, version); }); } installFromPathLockFree(location, options) { return __awaiter(this, void 0, void 0, function* () { const packageJson = yield this.readPackageJsonFromPath(location); if (!this.isValidPluginName(packageJson.name)) { throw new Error(`Invalid plugin name '${packageJson.name}'`); } // already installed satisfied version if (!options.force) { const installedInfo = this.alreadyInstalled(packageJson.name, packageJson.version); if (installedInfo) { return installedInfo; } } // already installed not satisfied version if (this.alreadyInstalled(packageJson.name)) { yield this.uninstallLockFree(packageJson.name); } // already downloaded if (options.force || !(yield this.isAlreadyDownloaded(packageJson.name, packageJson.version))) { yield this.removeDownloaded(packageJson.name); const destLocation = this.versionManager.getPath(packageJson); if (!destLocation) { throw new Error(`Cannot resolve path for ${packageJson.name}@${packageJson.version}`); } if (debug.enabled) { debug(`Copy from ${location} to ${destLocation}`); } yield fs.copy(location, destLocation, { exclude: ["node_modules"] }); } const pluginInfo = yield this.createPluginInfo(packageJson); return this.addPlugin(pluginInfo); }); } /** Install from npm or from cache if already available */ installFromNpmLockFreeCache(name, version = NPM_LATEST_TAG) { return __awaiter(this, void 0, void 0, function* () { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } version = this.validatePluginVersion(version); // already installed satisfied version const installedInfo = this.alreadyInstalled(name, version); if (installedInfo) { return installedInfo; } if (this.alreadyInstalled(name)) { // already installed not satisfied version, then uninstall it first yield this.uninstallLockFree(name); } if (this.options.npmInstallMode === "useCache" && (yield this.isAlreadyDownloaded(name, version))) { const packageJson = yield this.getDownloadedPackage(name, version); if (!packageJson) { throw new Error(`Unexpected state: not found ${name}@${version}`); } const pluginInfo = yield this.createPluginInfo(packageJson); return this.addPlugin(pluginInfo); } return this.installFromNpmLockFreeDirect(name, version); }); } /** Install from npm */ installFromNpmLockFreeDirect(name, version = NPM_LATEST_TAG) { return __awaiter(this, void 0, void 0, function* () { const registryInfo = yield this.npmRegistry.get(name, version); // already downloaded if (!(yield this.isAlreadyDownloaded(registryInfo.name, registryInfo.version))) { yield this.removeDownloaded(registryInfo.name); yield this.versionManager.download(this.npmRegistry, registryInfo); } const pluginInfo = yield this.createPluginInfo(registryInfo); return this.addPlugin(pluginInfo); }); } installFromGithubLockFree(repository) { return __awaiter(this, void 0, void 0, function* () { const registryInfo = yield this.githubRegistry.get(repository); if (!this.isValidPluginName(registryInfo.name)) { throw new Error(`Invalid plugin name '${registryInfo.name}'`); } // already installed satisfied version const installedInfo = this.alreadyInstalled(registryInfo.name, registryInfo.version); if (installedInfo) { return installedInfo; } // already installed not satisfied version if (this.alreadyInstalled(registryInfo.name)) { yield this.uninstallLockFree(registryInfo.name); } // already downloaded let downloadedInfo = undefined; if (!(yield this.isAlreadyDownloaded(registryInfo.name, registryInfo.version))) { yield this.removeDownloaded(registryInfo.name); downloadedInfo = yield this.versionManager.download(this.githubRegistry, registryInfo); } else { downloadedInfo = yield this.getDownloadedPackage(registryInfo.name, registryInfo.version); if (!downloadedInfo) { throw new Error(`Unexpected state: not found ${registryInfo.name}@${registryInfo.version}`); } } const pluginInfo = yield this.createPluginInfo(downloadedInfo); return this.addPlugin(pluginInfo); }); } installFromBitbucketLockFree(repository) { return __awaiter(this, void 0, void 0, function* () { const registryInfo = yield this.bitbucketRegistry.get(repository); if (!this.isValidPluginName(registryInfo.name)) { throw new Error(`Invalid plugin name '${registryInfo.name}'`); } // already installed satisfied version const installedInfo = this.alreadyInstalled(registryInfo.name, registryInfo.version); if (installedInfo) { return installedInfo; } // already installed not satisfied version if (this.alreadyInstalled(registryInfo.name)) { yield this.uninstallLockFree(registryInfo.name); } // already downloaded let downloadedInfo = undefined; if (!(yield this.isAlreadyDownloaded(registryInfo.name, registryInfo.version))) { yield this.removeDownloaded(registryInfo.name); downloadedInfo = yield this.versionManager.download(this.bitbucketRegistry, registryInfo); } else { downloadedInfo = yield this.getDownloadedPackage(registryInfo.name, registryInfo.version); if (!downloadedInfo) { throw new Error(`Unexpected state: not found ${registryInfo.name}@${registryInfo.version}`); } } const pluginInfo = yield this.createPluginInfo(downloadedInfo); return this.addPlugin(pluginInfo); }); } installFromCodeLockFree(name, code, version = "0.0.0") { return __awaiter(this, void 0, void 0, function* () { if (!this.isValidPluginName(name)) { throw new Error(`Invalid plugin name '${name}'`); } if (!semver.valid(version)) { throw new Error(`Invalid plugin version '${version}'`); } const packageJson = { name, version }; // already installed satisfied version if (version !== "0.0.0") { const installedInfo = this.alreadyInstalled(packageJson.name, packageJson.version); if (installedInfo) { return installedInfo; } } // already installed not satisfied version if (this.alreadyInstalled(packageJson.name)) { yield this.uninstallLockFree(packageJson.name); } // already created if (!(yield this.isAlreadyDownloaded(packageJson.name, packageJson.version))) { yield this.removeDownloaded(packageJson.name); if (debug.enabled) { debug(`Create plugin ${name} to ${this.options.pluginsPath} from code`); } const location = this.versionManager.getPath({ name, version }); if (!location) { throw new Error(`Cannot resolve path for ${name}@${version}`); } yield fs.remove(location); yield fs.ensureDir(location); yield fs.writeFile(path.join(location, VersionManager_1.DefaultMainFile), code); yield fs.writeFile(path.join(location, "package.json"), JSON.stringify(packageJson)); } const pluginInfo = yield this.createPluginInfo(packageJson); return this.addPlugin(pluginInfo); }); } installDependencies(plugin) { return __awaiter(this, void 0, void 0, function* () { if (!plugin.dependencies) { return {}; } const dependencies = {}; for (const key in plugin.dependencies) { if (!plugin.dependencies.hasOwnProperty(key)) { continue; } if (this.shouldIgnore(key)) { continue; } const version = plugin.dependencies[key]; if (this.isModuleAvailableFromHost(key, version)) { if (debug.enabled) { debug(`Installing dependencies of ${plugin.name}: ${key} is already available on host`); } } else if (this.alreadyInstalled(key, version)) { if (debug.enabled) { debug(`Installing dependencies of ${plugin.name}: ${key} is already installed`); } const installed = yield this.versionManager.resolvePath(key, version); if (!installed) { throw new Error(`Cannot resolve path for ${key}@${version}`); } yield this.linkDependencyToPlugin(plugin, key, installed); } else { if (debug.enabled) { debug(`Installing dependencies of ${plugin.name}: ${key} ...`); } const installedPlugin = yield this.installLockFree(key, version); const installed = yield this.versionManager.resolvePath(installedPlugin.name, installedPlugin.version); if (!installed) { throw new Error(`Cannot resolve path for ${installedPlugin.name}@${installedPlugin.version}`); } yield this.linkDependencyToPlugin(plugin, key, installed); } // NOTE: maybe here I should put the actual version? dependencies[key] = version; } return dependencies; }); } linkDependencyToPlugin(plugin, packageName, versionPath) { return __awaiter(this, void 0, void 0, function* () { const nodeModulesPath = path.join(plugin.location, "node_modules"); yield fs.ensureDir(nodeModulesPath); const modulePath = path.join(nodeModulesPath, packageName); const pathSegments = packageName.split("/"); for (let i = 1; i < pathSegments.length; i++) { const pathToCreate = path.join(nodeModulesPath, ...pathSegments.slice(0, i)); if (debug.enabled) { debug(`Creating ${pathToCreate}`); } yield fs.ensureDir(pathToCreate); } const moduleExists = yield fs.pathExists(modulePath); if (moduleExists) { // remove link if it exists if (debug.enabled) { debug(`Removing existing link ${modulePath}`); } yield fs.remove(modulePath); } yield fs.symlink(versionPath, modulePath); }); } unloadDependents(pluginName) { return __awaiter(this, void 0, void 0, function* () { for (const installed of this.installedPlugins) { if (installed.dependencies[pluginName]) { if (debug.enabled) { debug(`Attempting to unload dependent ${installed.name} of ${pluginName}...`); } yield this.unloadWithDependents(installed); } } }); } unloadWithDependents(plugin) { return __awaiter(this, void 0, void 0, function* () { this.unload(plugin); yield this.unloadDependents(plugin.name); }); } isModuleAvailableFromHost(name, version) { if (!this.options.hostRequire) { return false; } // TODO Here I should check also if version is compatible? // I can resolve the module, get the corresponding package.json // load it and get the version, then use // if (semver.satisfies(installedInfo.version, version)) // to check if compatible... try { const modulePackage = this.options.hostRequire(name + "/package.json"); return semver.satisfies(modulePackage.version, version); } catch (e) { return false; } } isValidPluginName(name) { if (typeof name !== "string") { return false; } if (name.length === 0) { return false; } // '/' is permitted to support scoped packages if (name.startsWith(".") || name.indexOf("\\") >= 0) { return false; } return true; } validatePluginVersion(version) { version = version || NPM_LATEST_TAG; if (typeof version !== "string") { throw new Error("Invalid version"); } return version; } getPluginLocation(name) { return path.join(this.options.pluginsPath, name); } removeDownloaded(name) { return __awaiter(this, void 0, void 0, function* () { const location = this.getPluginLocation(name); if (!(yield fs.directoryExists(location))) { yield fs.remove(location); } }); } isAlreadyDownloaded(name, version) { return __awaiter(this, void 0, void 0, function* () { if (!version) { version = ">0.0.1"; } if (version === NPM_LATEST_TAG) { return false; } const packageJson = yield this.getDownloadedPackage(name, version); if (!packageJson) { return false; } return packageJson.name === name && semver.satisfies(packageJson.version, version); }); } getDownloadedPackage(name, _version) { return __awaiter(this, void 0, void 0, function* () { const location = yield this.versionManager.resolvePath(name, _version); if (!location) { return; } if (!(yield fs.directoryExists(location))) { return; } try { const packageJson = yield this.readPackageJsonFromPath(location); return packageJson; } catch (e) { return; } }); } readPackageJsonFromPath(location) { return __awaiter(this, void 0, void 0, function* () { const packageJsonFile = path.join(location, "package.json"); if (!(yield fs.fileExists(packageJsonFile))) { throw new Error(`Invalid plugin ${location}, package.json is missing`); } const packageJson = JSON.parse(yield fs.readFile(packageJsonFile, "utf8")); if (!packageJson.name || !packageJson.version) { throw new Error(`Invalid plugin ${location}, 'main', 'name' and 'version' properties are required in package.json`); } return packageJson; }); } load(plugin, filePath) { filePath = filePath || plugin.mainFile; const resolvedPath = this.vm.resolve(plugin, filePath); if (debug.enabled) { debug(`Loading ${filePath} of ${plugin.name} (${resolvedPath})...`); } return this.vm.load(plugin, resolvedPath); } unload(plugin) { if (debug.enabled) { debug(`Unloading ${plugin.name}...`); } this.vm.unload(plugin); } addPlugin(plugin) { return __awaiter(this, void 0, void 0, function* () { yield this.installDependencies(plugin); const oldPluginIndex = this.installedPlugins.findIndex(p => p.name === plugin.name); if (oldPluginIndex !== -1) { const oldPlugins = this.installedPlugins.splice(oldPluginIndex, 1); yield this.unlinkModule(oldPlugins[0]); } const linkedPlugin = yield this.linkModule(plugin); this.installedPlugins.push(linkedPlugin); // this.unloadDependents(plugin.name); return linkedPlugin; }); } /** * Unlink a plugin from the specified version of package. * * @param plugin A plugin information to unlink */ unlinkModule(plugin) { return __awaiter(this, void 0, void 0, function* () { const location = this.getPluginLocation(plugin.name); if (debug.enabled) { debug(`Unlinking ${location} to ${plugin.name}@${plugin.version}`); } const pathSegments = plugin.name.split("/"); for (let i = 0; i < pathSegments.length; i++) { const pathToRemove = path.join(this.options.pluginsPath, ...pathSegments.slice(0, pathSegments.length - i)); if (debug.enabled) { debug(`Removing ${pathToRemove}`); } if (!(yield fs.directoryExists(pathToRemove))) { continue; } if (i > 0) { const files = yield fs.readdir(pathToRemove); if (files.length > 0) { if (debug.enabled) { debug(`Skipping ${pathToRemove} as it is not empty`); } break; } } yield fs.remove(pathToRemove); } yield this.versionManager.uninstallOrphan(plugin); }); } /** * Link a plugin to the specified version of package. * * @param plugin A plugin information to link * @returns A plugin information linked */ linkModule(plugin) { return __awaiter(this, void 0, void 0, function* () { const location = this.getPluginLocation(plugin.name); const versionLocation = this.versionManager.getPath(plugin); if (!versionLocation) { throw new Error(`Cannot resolve path for ${plugin.name}@${plugin.version}`); } if (debug.enabled) { debug(`Linking ${location} to ${versionLocation}`); } yield fs.remove(location); // parent directory should be created before linking yield fs.ensureDir(path.dirname(location)); yield fs.symlink(versionLocation, location); return this.createPluginInfoFromPath(location, true); }); } deleteAndUnloadPlugin(plugin) { return __awaiter(this, void 0, void 0, function* () { const index = this.installedPlugins.indexOf(plugin); if (index >= 0) { this.installedPlugins.splice(index, 1); } this.sandboxTemplates.delete(plugin.name); yield this.unloadWithDependents(plugin); yield this.unlinkModule(plugin); }); } syncLock() { if (debug.enabled) { debug("Acquiring lock ..."); } const lockLocation = path.join(this.options.pluginsPath, "install.lock"); return new Promise((resolve, reject) => { lockFile.lock(lockLocation, { wait: this.options.lockWait, stale: this.options.lockStale }, (err) => { if (err) { if (debug.enabled) { debug("Failed to acquire lock", err); } return reject("Failed to acquire lock: " + err.message); } resolve(); }); }); } syncUnlock() { if (debug.enabled) { debug("Releasing lock ..."); } const lockLocation = path.join(this.options.pluginsPath, "install.lock"); return new Promise((resolve, reject) => { lockFile.unlock(lockLocation, (err) => { if (err) { if (debug.enabled) { debug("Failed to release lock", err); } return reject("Failed to release lock: " + err.message); } resolve(); }); }); } shouldIgnore(name) { for (const p of this.options.ignoredDependencies) { let ignoreMe = false; if (p instanceof RegExp) { ignoreMe = p.test(name); if (ignoreMe) { return true; } } ignoreMe = new RegExp(p).test(name); if (ignoreMe) { return true; } } for (const key in this.options.staticDependencies) { if (!this.options.staticDependencies.hasOwnProperty(key)) { continue; } if (key === name) { return true; } } return false; } createPluginInfo(packageInfo) { return __awaiter(this, void 0, void 0, function* () { const { name, version } = packageInfo; const location = yield this.versionManager.resolvePath(name, version); if (!location) { throw new Error(`Cannot resolve path for ${name}@${version}`); } return this.createPluginInfoFromPath(location); }); } /** * Create a plugin information from the specified location. * * @param location A location of the plugin * @param withDependencies If true, dependencies are also loaded * @returns */ createPluginInfoFromPath(location, withDependencies = false) { return __awaiter(this, void 0, void 0, function* () { return this.versionManager.createVersionInfoFromPath(location, withDependencies); }); } } exports.PluginManager = PluginManager; //# sourceMappingURL=PluginManager.js.map