UNPKG

judpack-common

Version:
279 lines (240 loc) 9.65 kB
/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ /* jshint sub:true */ var fs = require('fs'); var path = require('path'); var shelljs = require('shelljs'); var mungeutil = require('./ConfigChanges/munge-util'); var pluginMappernto = require('cordova-registry-mapper').newToOld; var pluginMapperotn = require('cordova-registry-mapper').oldToNew; function PlatformJson(filePath, platform, root) { this.filePath = filePath; this.platform = platform; this.root = fix_munge(root || {}); } PlatformJson.load = function(plugins_dir, platform) { var filePath = path.join(plugins_dir, platform + '.json'); var root = null; if (fs.existsSync(filePath)) { root = JSON.parse(fs.readFileSync(filePath, 'utf-8')); } return new PlatformJson(filePath, platform, root); }; PlatformJson.prototype.save = function() { shelljs.mkdir('-p', path.dirname(this.filePath)); fs.writeFileSync(this.filePath, JSON.stringify(this.root, null, 4), 'utf-8'); }; /** * Indicates whether the specified plugin is installed as a top-level (not as * dependency to others) * @method function * @param {String} pluginId A plugin id to check for. * @return {Boolean} true if plugin installed as top-level, otherwise false. */ PlatformJson.prototype.isPluginTopLevel = function(pluginId) { var installedPlugins = this.root.installed_plugins; return installedPlugins[pluginId] || installedPlugins[pluginMappernto[pluginId]] || installedPlugins[pluginMapperotn[pluginId]]; }; /** * Indicates whether the specified plugin is installed as a dependency to other * plugin. * @method function * @param {String} pluginId A plugin id to check for. * @return {Boolean} true if plugin installed as a dependency, otherwise false. */ PlatformJson.prototype.isPluginDependent = function(pluginId) { var dependentPlugins = this.root.dependent_plugins; return dependentPlugins[pluginId] || dependentPlugins[pluginMappernto[pluginId]] || dependentPlugins[pluginMapperotn[pluginId]]; }; /** * Indicates whether plugin is installed either as top-level or as dependency. * @method function * @param {String} pluginId A plugin id to check for. * @return {Boolean} true if plugin installed, otherwise false. */ PlatformJson.prototype.isPluginInstalled = function(pluginId) { return this.isPluginTopLevel(pluginId) || this.isPluginDependent(pluginId); }; PlatformJson.prototype.addPlugin = function(pluginId, variables, isTopLevel) { var pluginsList = isTopLevel ? this.root.installed_plugins : this.root.dependent_plugins; pluginsList[pluginId] = variables; return this; }; /** * @chaining * Generates and adds metadata for provided plugin into associated <platform>.json file * * @param {PluginInfo} pluginInfo A pluginInfo instance to add metadata from * @returns {this} Current PlatformJson instance to allow calls chaining */ PlatformJson.prototype.addPluginMetadata = function (pluginInfo) { var installedModules = this.root.modules || []; var installedPaths = installedModules.map(function (installedModule) { return installedModule.file; }); var modulesToInstall = pluginInfo.getJsModules(this.platform) .map(function (module) { return new ModuleMetadata(pluginInfo.id, module); }) .filter(function (metadata) { // Filter out modules which are already added to metadata return installedPaths.indexOf(metadata.file) === -1; }); this.root.modules = installedModules.concat(modulesToInstall); this.root.plugin_metadata = this.root.plugin_metadata || {}; this.root.plugin_metadata[pluginInfo.id] = pluginInfo.version; return this; }; PlatformJson.prototype.removePlugin = function(pluginId, isTopLevel) { var pluginsList = isTopLevel ? this.root.installed_plugins : this.root.dependent_plugins; delete pluginsList[pluginId]; return this; }; /** * @chaining * Removes metadata for provided plugin from associated file * * @param {PluginInfo} pluginInfo A PluginInfo instance to which modules' metadata * we need to remove * * @returns {this} Current PlatformJson instance to allow calls chaining */ PlatformJson.prototype.removePluginMetadata = function (pluginInfo) { var modulesToRemove = pluginInfo.getJsModules(this.platform) .map(function (jsModule) { return ['plugins', pluginInfo.id, jsModule.src].join('/'); }); var installedModules = this.root.modules || []; this.root.modules = installedModules .filter(function (installedModule) { // Leave only those metadatas which 'file' is not in removed modules return (modulesToRemove.indexOf(installedModule.file) === -1); }); if (this.root.plugin_metadata) { delete this.root.plugin_metadata[pluginInfo.id]; } return this; }; PlatformJson.prototype.addInstalledPluginToPrepareQueue = function(pluginDirName, vars, is_top_level, force) { this.root.prepare_queue.installed.push({'plugin':pluginDirName, 'vars':vars, 'topLevel':is_top_level, 'force':force}); }; PlatformJson.prototype.addUninstalledPluginToPrepareQueue = function(pluginId, is_top_level) { this.root.prepare_queue.uninstalled.push({'plugin':pluginId, 'id':pluginId, 'topLevel':is_top_level}); }; /** * Moves plugin, specified by id to top-level plugins. If plugin is top-level * already, then does nothing. * @method function * @param {String} pluginId A plugin id to make top-level. * @return {PlatformJson} PlatformJson instance. */ PlatformJson.prototype.makeTopLevel = function(pluginId) { var plugin = this.root.dependent_plugins[pluginId]; if (plugin) { delete this.root.dependent_plugins[pluginId]; this.root.installed_plugins[pluginId] = plugin; } return this; }; /** * Generates a metadata for all installed plugins and js modules. The resultant * string is ready to be written to 'cordova_plugins.js' * * @returns {String} cordova_plugins.js contents */ PlatformJson.prototype.generateMetadata = function () { return [ 'cordova.define(\'cordova/plugin_list\', function(require, exports, module) {', 'module.exports = ' + JSON.stringify(this.root.modules, null, 4) + ';', 'module.exports.metadata = ', '// TOP OF METADATA', JSON.stringify(this.root.plugin_metadata, null, 4) + ';', '// BOTTOM OF METADATA', '});' // Close cordova.define. ].join('\n'); }; /** * @chaining * Generates and then saves metadata to specified file. Doesn't check if file exists. * * @param {String} destination File metadata will be written to * @return {PlatformJson} PlatformJson instance */ PlatformJson.prototype.generateAndSaveMetadata = function (destination) { var meta = this.generateMetadata(); shelljs.mkdir('-p', path.dirname(destination)); fs.writeFileSync(destination, meta, 'utf-8'); return this; }; // convert a munge from the old format ([file][parent][xml] = count) to the current one function fix_munge(root) { root.prepare_queue = root.prepare_queue || {installed:[], uninstalled:[]}; root.config_munge = root.config_munge || {files: {}}; root.installed_plugins = root.installed_plugins || {}; root.dependent_plugins = root.dependent_plugins || {}; var munge = root.config_munge; if (!munge.files) { var new_munge = { files: {} }; for (var file in munge) { for (var selector in munge[file]) { for (var xml_child in munge[file][selector]) { var val = parseInt(munge[file][selector][xml_child]); for (var i = 0; i < val; i++) { mungeutil.deep_add(new_munge, [file, selector, { xml: xml_child, count: val }]); } } } } root.config_munge = new_munge; } return root; } /** * @constructor * @class ModuleMetadata * * Creates a ModuleMetadata object that represents module entry in 'cordova_plugins.js' * file at run time * * @param {String} pluginId Plugin id where this module installed from * @param (JsModule|Object) jsModule A js-module entry from PluginInfo class to generate metadata for */ function ModuleMetadata (pluginId, jsModule) { if (!pluginId) throw new TypeError('pluginId argument must be a valid plugin id'); if (!jsModule.src && !jsModule.name) throw new TypeError('jsModule argument must contain src or/and name properties'); this.id = pluginId + '.' + ( jsModule.name || jsModule.src.match(/([^\/]+)\.js/)[1] ); this.file = ['plugins', pluginId, jsModule.src].join('/'); this.pluginId = pluginId; if (jsModule.clobbers && jsModule.clobbers.length > 0) { this.clobbers = jsModule.clobbers.map(function(o) { return o.target; }); } if (jsModule.merges && jsModule.merges.length > 0) { this.merges = jsModule.merges.map(function(o) { return o.target; }); } if (jsModule.runs) { this.runs = true; } } module.exports = PlatformJson;