UNPKG

zombiebox

Version:

ZombieBox is a JavaScript framework for development of Smart TV and STB applications

157 lines (129 loc) 3.33 kB
/* * This file is part of the ZombieBox package. * * Copyright © 2012-2019, Interfaced * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const {findPackageJson} = require('../utils'); const AbstractAddon = require('./abstract-addon'); const AbstractPlatform = require('./abstract-platform'); const AbstractExtension = require('./abstract-extension'); /* eslint-disable global-require */ /** */ class AddonLoader { /** * @param {string} projectModulesDir */ constructor(projectModulesDir) { /** * @type {string} * @private */ this._projectModulesDir = projectModulesDir; /** * @type {Array<LoadedAddon>} * @private */ this._loadedAddons = []; } /** * @return {Array<Object>} */ getPackageJsons() { return this._loadedAddons.map((addon) => addon.packageJson) .filter(Boolean); } /** * @return {Array<AbstractAddon>} */ getAddons() { return this._loadedAddons.map((addon) => addon.instance); } /** * @return {Array<AbstractExtension>} */ getExtensions() { return this.getAddons() .filter((addon) => addon instanceof AbstractExtension); } /** * @return {Array<AbstractPlatform>} */ getPlatforms() { return this.getAddons() .filter((addon) => addon instanceof AbstractPlatform); } /** * @param {Object} packageJson */ loadFromPackageJson(packageJson) { Object.keys(packageJson['dependencies'] || {}) .filter((packageName) => packageName.startsWith(PACKAGE_PREFIX)) .map((packageName) => this._resolvePackagePath(packageName)) .forEach((packagePath) => this.loadAddon(packagePath)); } /** * @param {string} addonPath */ loadAddon(addonPath) { const Addon = require(addonPath); const addon = /** @type {AbstractAddon} */ (new Addon()); const packageJson = require(findPackageJson(addonPath)); this.addAddon(addon, packageJson); } /** * @param {AbstractAddon} addon * @param {Object=} packageJson */ addAddon(addon, packageJson = null) { if (!(addon instanceof AbstractAddon)) { throw new Error(`Trying to add not addon: ${addon}`); } if (this._isLoaded(addon)) { throw new Error(`Addon with name ${chalk.bold(addon.getName())} is already loaded`); } this._loadedAddons.push({instance: addon, packageJson}); const type = addon instanceof AbstractPlatform ? 'Platform' : addon instanceof AbstractExtension ? 'Extension' : 'Addon'; console.log(`${type} ${chalk.green(addon.getName())} loaded`); } /** * @param {string} packageName * @return {string} * @protected */ _resolvePackagePath(packageName) { const localPackage = path.join(this._projectModulesDir, packageName); return fs.existsSync(localPackage) ? localPackage : require.resolve(packageName); } /** * @param {AbstractAddon} addon * @return {boolean} * @protected */ _isLoaded(addon) { return this._loadedAddons.some((loadedAddon) => loadedAddon.instance.getName() === addon.getName() ); } } /** * @const {string} */ const PACKAGE_PREFIX = 'zombiebox-'; /** * @typedef {{ * instance: AbstractAddon, * packageJson: ?Object * }} */ let LoadedAddon; module.exports = AddonLoader;