選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

index.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*!
  2. * get-installed-path <https://github.com/tunnckoCore/get-installed-path>
  3. *
  4. * Copyright (c) Charlike Mike Reagent <@tunnckoCore> (http://i.am.charlike.online)
  5. * Released under the MIT license.
  6. */
  7. 'use strict'
  8. const fs = require('fs')
  9. const path = require('path')
  10. const modules = require('global-modules')
  11. /**
  12. * > Get installed path of globally or locally `name` package.
  13. * By default it checks if `name` exists as directory in [global-modules][]
  14. * directory of the system. Pass `opts.local` to get path of `name`
  15. * package from local directory or from `opts.cwd`. Returns rejected
  16. * promise if module not found in global/local `node_modules` folder or
  17. * if it exist but is not a directory.
  18. *
  19. * **Example**
  20. *
  21. * ```js
  22. * const getInstalledPath = require('get-installed-path')
  23. *
  24. * getInstalledPath('npm').then((path) => {
  25. * console.log(path)
  26. * // => '/home/charlike/.nvm/path/to/lib/node_modules/npm'
  27. * })
  28. *
  29. * getInstalledPath('foo-bar-barwerwlekrjw').catch((err) => {
  30. * console.log(err.message)
  31. * // => 'module not found "foo-bar-barwerwlekrjw" in path ...'
  32. * })
  33. *
  34. * getInstalledPath('npm', {
  35. * local: true
  36. * }).catch((err) => {
  37. * console.log(err.message)
  38. * // => 'module not found "foo-bar-barwerwlekrjw" in path ...'
  39. * })
  40. *
  41. * getInstalledPath('global-modules', {
  42. * local: true
  43. * }).then((path) => {
  44. * console.log(path)
  45. * // => '~/code/get-installed-path/node_modules/global-modules'
  46. * })
  47. *
  48. * // If you are using it for some sub-directory
  49. * // pass `opts.cwd` to be where the `node_modules`
  50. * // folder is.
  51. * process.chidr('foo-bar-baz')
  52. * getInstalledPath('global-modules', {
  53. * local: true,
  54. * cwd: '../'
  55. * }).then((path) => {
  56. * console.log(path)
  57. * // => '~/code/get-installed-path/node_modules/global-modules'
  58. * })
  59. *
  60. * // When searching for the path of a package that is required
  61. * // by several other packages, its path may not be in the
  62. * // closest node_modules. In this case, to search recursively,
  63. * // you can use the following:
  64. * getInstalledPath('npm', {
  65. * paths: process.mainModule.paths
  66. * }).then((path) => {
  67. * // ...
  68. * })
  69. * // `process.mainModule` refers to the location of the current
  70. * // entry script.
  71. * ```
  72. *
  73. * @param {String} `name` package name
  74. * @param {Object} `opts` pass `opts.local` to check locally
  75. * @return {Promise} rejected promise if `name` not a string or is empty string
  76. * @api public
  77. */
  78. module.exports = function getInstalledPath (name, opts) {
  79. return new Promise((resolve, reject) => {
  80. if (!isValidString(name)) {
  81. const message = 'get-installed-path: expect `name` to be string'
  82. return reject(new TypeError(message))
  83. }
  84. const targetPaths = defaults(name, opts)
  85. const statPath = (filepath) =>
  86. fs.stat(filepath, (e, stats) => {
  87. if (e && targetPaths.length > 0) {
  88. statPath(targetPaths.shift())
  89. return
  90. } else if (e) {
  91. const label = 'get-installed-path:'
  92. const msg = `${label} module not found "${name}" in path ${filepath}`
  93. return reject(new Error(msg))
  94. }
  95. if (stats.isDirectory()) {
  96. return resolve(filepath)
  97. }
  98. const msg = `Possibly "${name}" is not a directory: ${filepath}`
  99. let err = new Error('get-installed-path: some error occured! ' + msg)
  100. reject(err)
  101. })
  102. statPath(targetPaths.shift())
  103. })
  104. }
  105. /**
  106. * > Get installed path of a `name` package synchronous.
  107. *
  108. * **Example**
  109. *
  110. * ```js
  111. * const getInstalledPath = require('get-installed-path')
  112. *
  113. * const npmPath = getInstalledPath.sync('npm')
  114. * console.log(npmPath)
  115. * // => '/home/charlike/.nvm/path/to/lib/node_modules/npm'
  116. *
  117. * const gmPath = getInstalledPath.sync('global-modules', { local: true })
  118. * console.log(gmPath)
  119. * // => '~/code/get-installed-path/node_modules/global-modules'
  120. * ```
  121. *
  122. * @name .sync
  123. * @param {String} `name` package name
  124. * @param {Object} `opts` pass `opts.local` to check locally
  125. * @return {Boolean} or throw `TypeError` if `name` not a string or is empty string
  126. * @api public
  127. */
  128. module.exports.sync = function getInstalledPathSync (name, opts) {
  129. if (!isValidString(name)) {
  130. throw new TypeError('get-installed-path: expect `name` to be string')
  131. }
  132. const filePaths = defaults(name, opts)
  133. const firstPath = filePaths[0]
  134. const modulePath = filePaths.find((filePath) => {
  135. let stat = null
  136. try {
  137. stat = fs.statSync(filePath)
  138. } catch (e) {
  139. return false
  140. }
  141. if (stat.isDirectory()) {
  142. return true
  143. }
  144. const msg = `Possibly "${name}" is not a directory: ${filePath}`
  145. throw new Error('get-installed-path: some error occured! ' + msg)
  146. })
  147. if (!modulePath) {
  148. const label = 'get-installed-path:'
  149. const msg = `${label} module not found "${name}" in path ${firstPath}`
  150. throw new Error(msg)
  151. }
  152. return modulePath
  153. }
  154. function isValidString (val) {
  155. return typeof val === 'string' ? val.length > 0 : false
  156. }
  157. function defaults (name, opts) {
  158. opts = opts && typeof opts === 'object' ? opts : {}
  159. opts.cwd = typeof opts.cwd === 'string' ? opts.cwd : process.cwd()
  160. if (opts.paths) {
  161. return opts.paths.map((modulePath) => path.join(modulePath, name))
  162. } else if (opts.local) {
  163. return [path.join(opts.cwd, 'node_modules', name)]
  164. }
  165. return [path.join(modules, name)]
  166. }