Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

index.js 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. 'License'); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing,
  11. software distributed under the License is distributed on an
  12. 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. KIND, either express or implied. See the License for the
  14. specific language governing permissions and limitations
  15. under the License.
  16. */
  17. const pify = require('pify');
  18. const which = pify(require('which'));
  19. const path = require('path');
  20. const fs = require('fs-extra');
  21. const { CordovaError, events, superspawn } = require('cordova-common');
  22. const resolve = pify(require('resolve'), { multiArgs: true });
  23. const npa = require('npm-package-arg');
  24. const semver = require('semver');
  25. /**
  26. * Installs a module from npm, a git url or the local file system.
  27. *
  28. * @param {String} target A spec for the package to be installed
  29. * (anything supported by `npm install`)
  30. * @param {String} dest Location where to install the package
  31. * @param {Object} [opts={}] Additional options
  32. *
  33. * @return {Promise<string>} Absolute path to the installed package
  34. */
  35. module.exports = function (target, dest, opts = {}) {
  36. return Promise.resolve()
  37. .then(() => {
  38. if (!dest || !target) {
  39. throw new CordovaError('Need to supply a target and destination');
  40. }
  41. // Create dest if it doesn't exist yet
  42. fs.ensureDirSync(dest);
  43. })
  44. .then(_ => {
  45. return pathToInstalledPackage(target, dest)
  46. .catch(_ => installPackage(target, dest, opts));
  47. })
  48. .catch(err => {
  49. throw new CordovaError(err);
  50. });
  51. };
  52. // Installs the package specified by target and returns the installation path
  53. function installPackage (target, dest, opts) {
  54. return isNpmInstalled()
  55. // Ensure that `npm` installs to `dest` and not any of its ancestors
  56. .then(_ => fs.ensureDir(path.join(dest, 'node_modules')))
  57. // Run `npm` to install requested package
  58. .then(_ => npmArgs(target, opts))
  59. .then(args => {
  60. events.emit('verbose', `fetch: Installing ${target} to ${dest}`);
  61. return superspawn.spawn('npm', args, { cwd: dest });
  62. })
  63. // Resolve path to installed package
  64. .then(getTargetPackageSpecFromNpmInstallOutput)
  65. .then(spec => pathToInstalledPackage(spec, dest));
  66. }
  67. function npmArgs (target, opts) {
  68. const args = ['install', target];
  69. opts = opts || {};
  70. if (opts.save_exact) {
  71. args.push('--save-exact');
  72. } else if (opts.save) {
  73. args.push('--save-dev');
  74. } else {
  75. args.push('--no-save');
  76. }
  77. return args;
  78. }
  79. function getTargetPackageSpecFromNpmInstallOutput (npmInstallOutput) {
  80. const packageInfoLine = npmInstallOutput.split('\n')
  81. .find(line => line.startsWith('+ '));
  82. if (!packageInfoLine) {
  83. throw new CordovaError(`Could not determine package name from output:\n${npmInstallOutput}`);
  84. }
  85. return packageInfoLine.slice(2);
  86. }
  87. // Resolves to installation path of package defined by spec if the right version
  88. // is installed, rejects otherwise.
  89. function pathToInstalledPackage (spec, dest) {
  90. return Promise.resolve().then(_ => {
  91. const { name, rawSpec } = npa(spec, dest);
  92. if (!name) {
  93. throw new CordovaError(`Cannot determine package name from spec ${spec}`);
  94. }
  95. return resolvePathToPackage(name, dest)
  96. .then(([pkgPath, { version }]) => {
  97. if (!semver.satisfies(version, rawSpec)) {
  98. throw new CordovaError(`Installed package ${name}@${version} does not satisfy ${name}@${rawSpec}`);
  99. }
  100. return pkgPath;
  101. });
  102. });
  103. }
  104. // Resolves to installation path and package.json of package `name` starting
  105. // from `basedir`
  106. function resolvePathToPackage (name, basedir) {
  107. return Promise.resolve().then(_ => {
  108. const paths = (process.env.NODE_PATH || '')
  109. .split(path.delimiter)
  110. .filter(p => p);
  111. // We resolve the path to the module's package.json to avoid getting the
  112. // path to `main` which could be located anywhere in the package
  113. return resolve(path.join(name, 'package.json'), { paths, basedir })
  114. .then(([pkgJsonPath, pkgJson]) => [
  115. path.dirname(pkgJsonPath), pkgJson
  116. ]);
  117. });
  118. }
  119. /**
  120. * Checks to see if npm is installed on the users system
  121. *
  122. * @return {Promise<string>} Absolute path to npm.
  123. */
  124. function isNpmInstalled () {
  125. return which('npm').catch(_ => {
  126. throw new CordovaError('"npm" command line tool is not installed: make sure it is accessible on your PATH.');
  127. });
  128. }
  129. module.exports.isNpmInstalled = isNpmInstalled;
  130. /**
  131. * Uninstalls the package `target` from `dest` using given options.
  132. *
  133. * @param {String} target Name of the package to be uninstalled
  134. * @param {String} dest Location from where to uninstall the package
  135. * @param {Object} [opts={}] Additional options
  136. *
  137. * @return {Promise<string>} Resolves when removal has finished
  138. */
  139. module.exports.uninstall = (target, dest, opts) => {
  140. const fetchArgs = ['uninstall'];
  141. opts = opts || {};
  142. // check if npm is installed on the system
  143. return isNpmInstalled()
  144. .then(() => {
  145. if (dest && target) {
  146. // add target to fetchArgs Array
  147. fetchArgs.push(target);
  148. } else throw new CordovaError('Need to supply a target and destination');
  149. // set the directory where npm uninstall will be run
  150. opts.cwd = dest;
  151. // if user added --save flag, pass --save-dev flag to npm uninstall command
  152. if (opts.save) {
  153. fetchArgs.push('--save-dev');
  154. } else {
  155. fetchArgs.push('--no-save');
  156. }
  157. // run npm uninstall, this will remove dependency
  158. // from package.json if --save was used.
  159. return superspawn.spawn('npm', fetchArgs, opts);
  160. })
  161. .catch(err => {
  162. throw new CordovaError(err);
  163. });
  164. };