UNPKG

nativescript

Version:

Command-line interface for building NativeScript projects

209 lines • 10.8 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExtensibilityService = void 0; const path = require("path"); const _ = require("lodash"); const decorators_1 = require("../common/decorators"); const constants = require("../constants"); const helpers_1 = require("../common/helpers"); const yok_1 = require("../common/yok"); class ExtensibilityService { get pathToPackageJson() { return path.join(this.pathToExtensions, constants.PACKAGE_JSON_FILE_NAME); } get pathToExtensions() { return (this.customPathToExtensions || path.join(this.$settingsService.getProfileDir(), "extensions")); } set pathToExtensions(pathToExtensions) { this.customPathToExtensions = pathToExtensions; } constructor($fs, $logger, $packageManager, $settingsService, $requireService) { this.$fs = $fs; this.$logger = $logger; this.$packageManager = $packageManager; this.$settingsService = $settingsService; this.$requireService = $requireService; this.customPathToExtensions = null; } async installExtension(extensionName) { this.$logger.trace(`Start installation of extension '${extensionName}'.`); await this.assertPackageJsonExists(); const npmOpts = { save: true, ["save-exact"]: true, }; const localPath = path.resolve(extensionName); const packageName = this.$fs.exists(localPath) ? localPath : extensionName; const installResultInfo = await this.$packageManager.install(packageName, this.pathToExtensions, npmOpts); this.$logger.trace(`Finished installation of extension '${extensionName}'. Trying to load it now.`); return this.getInstalledExtensionData(installResultInfo.name); } async uninstallExtension(extensionName) { this.$logger.trace(`Start uninstallation of extension '${extensionName}'.`); await this.assertPackageJsonExists(); await this.$packageManager.uninstall(extensionName, { save: true }, this.pathToExtensions); this.$logger.trace(`Finished uninstallation of extension '${extensionName}'.`); } removeAllExtensions() { this.$fs.deleteDirectorySafe(this.pathToExtensions); this.$logger.info(`Removed all NativeScript CLI extensions.`); } getInstalledExtensionsData() { const installedExtensions = this.getInstalledExtensions(); return _.keys(installedExtensions).map((installedExtension) => this.getInstalledExtensionData(installedExtension)); } loadExtensions() { this.$logger.trace("Loading extensions."); let dependencies = null; try { dependencies = this.getInstalledExtensions(); } catch (err) { this.$logger.trace(`Error while getting installed dependencies: ${err.message}. No extensions will be loaded.`); } return _.keys(dependencies).map((name) => this.loadExtension(name)); } getInstalledExtensions() { if (this.$fs.exists(this.pathToPackageJson)) { return this.$fs.readJson(this.pathToPackageJson).dependencies; } return null; } getInstalledExtensionData(extensionName) { const packageJsonData = this.getExtensionPackageJsonData(extensionName); const pathToExtension = this.getPathToExtension(extensionName); const docs = packageJsonData && packageJsonData.nativescript && packageJsonData.nativescript.docs && path.join(pathToExtension, packageJsonData.nativescript.docs); return { extensionName: packageJsonData.name, version: packageJsonData.version, docs, pathToExtension, }; } async loadExtension(extensionName) { try { await this.assertExtensionIsInstalled(extensionName); const pathToExtension = this.getPathToExtension(extensionName); this.$requireService.require(pathToExtension); return this.getInstalledExtensionData(extensionName); } catch (error) { this.$logger.warn(`Error while loading ${extensionName} is: ${error.message}`); const err = (new Error(`Unable to load extension ${extensionName}. You will not be able to use the functionality that it adds. Error: ${error.message}`)); err.extensionName = extensionName; throw err; } } async getExtensionNameWhereCommandIsRegistered(inputOpts) { let allExtensions = []; try { const npmsResult = await this.$packageManager.searchNpms("nativescript:extension"); allExtensions = npmsResult.results || []; } catch (err) { this.$logger.trace(`Unable to find extensions via npms. Error is: ${err}`); return null; } const defaultCommandRegExp = new RegExp(`${(0, helpers_1.regExpEscape)(inputOpts.defaultCommandDelimiter)}.*`); const commandDelimiterRegExp = (0, helpers_1.createRegExp)(inputOpts.commandDelimiter, "g"); for (const extensionData of allExtensions) { const extensionName = extensionData.package.name; try { // now get full package.json for the latest version of the package const registryData = await this.$packageManager.getRegistryPackageData(extensionName); const latestPackageData = registryData.versions[registryData["dist-tags"].latest]; const commands = latestPackageData && latestPackageData.nativescript && latestPackageData.nativescript.commands; if (commands && commands.length) { // For each default command we need to add its short syntax in the array of commands. // For example in case there's a default command called devices list, the commands array will contain devices|*list. // However, in case the user executes just tns devices, CLI will still execute the tns devices list command. // So we need to add the devices command as well. _.filter(commands, (command) => command.indexOf(inputOpts.defaultCommandDelimiter) !== -1).forEach((defaultCommand) => { commands.push(defaultCommand.replace(defaultCommandRegExp, "")); }); const copyOfFullArgs = _.clone(inputOpts.inputStrings); while (copyOfFullArgs.length) { const currentCommand = copyOfFullArgs .join(inputOpts.commandDelimiter) .toLowerCase(); if (_.some(commands, (c) => c.toLowerCase() === currentCommand)) { const beautifiedCommandName = currentCommand.replace(commandDelimiterRegExp, " "); return { extensionName, registeredCommandName: currentCommand, installationMessage: `The command ${beautifiedCommandName} is registered in extension ${extensionName}. You can install it by executing 'tns extension install ${extensionName}'`, }; } copyOfFullArgs.splice(-1, 1); } } } catch (err) { // We do not want to stop the whole process in case we are unable to find data for one of the extensions. this.$logger.trace(`Unable to get data for ${extensionName}. Error is: ${err}`); } } return null; } getPathToExtension(extensionName) { return path.join(this.pathToExtensions, constants.NODE_MODULES_FOLDER_NAME, extensionName); } getExtensionPackageJsonData(extensionName) { const pathToExtension = this.getPathToExtension(extensionName); const pathToPackageJson = path.join(pathToExtension, constants.PACKAGE_JSON_FILE_NAME); const jsonData = this.$fs.readJson(pathToPackageJson); return jsonData; } async assertExtensionIsInstalled(extensionName) { this.$logger.trace(`Asserting extension ${extensionName} is installed.`); const installedExtensions = this.$fs.readDirectory(path.join(this.pathToExtensions, constants.NODE_MODULES_FOLDER_NAME)); if (installedExtensions.indexOf(extensionName) === -1) { this.$logger.trace(`Extension ${extensionName} is not installed, starting installation.`); await this.installExtension(extensionName); } this.$logger.trace(`Extension ${extensionName} is installed.`); } assertExtensionsDirExists() { if (!this.$fs.exists(this.pathToExtensions)) { this.$fs.createDirectory(this.pathToExtensions); } } assertPackageJsonExists() { this.assertExtensionsDirExists(); if (!this.$fs.exists(this.pathToPackageJson)) { this.$logger.trace(`Creating ${this.pathToPackageJson}.`); // create default package.json this.$fs.writeJson(this.pathToPackageJson, { name: "nativescript-extensibility", version: "1.0.0", description: "The place where all packages that extend CLI will be installed.", license: "Apache-2.0", readme: "The place where all packages that extend CLI will be installed.", repository: "none", dependencies: {}, }); this.$logger.trace(`Created ${this.pathToPackageJson}.`); } } } exports.ExtensibilityService = ExtensibilityService; __decorate([ (0, decorators_1.cache)() ], ExtensibilityService.prototype, "assertExtensionsDirExists", null); __decorate([ (0, decorators_1.cache)() ], ExtensibilityService.prototype, "assertPackageJsonExists", null); yok_1.injector.register("extensibilityService", ExtensibilityService); //# sourceMappingURL=extensibility-service.js.map