├── .gitattributes ├── renovate.json ├── .eslintrc ├── .eslintrc.json ├── .nycrc.json ├── .helarc ├── .editorconfig ├── .prettierrc ├── .codeclimate.yml ├── .travis.yml ├── .github └── FUNDING.yml ├── LICENSE ├── .gitignore ├── .eslintignore ├── package.json ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── src └── index.js ├── CONTRIBUTING.md ├── test └── index.js ├── .verb.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | * text eol=lf 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tunnckocore" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "standard-tunnckocore" 4 | ], 5 | "rules": { 6 | "react/react-in-jsx-scope": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "standard-tunnckocore" 4 | ], 5 | "rules": { 6 | "react/react-in-jsx-scope": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "statements": 100, 3 | "functions": 100, 4 | "branches": 100, 5 | "lines": 100, 6 | "exclude": [ 7 | "dist" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.helarc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": "hela-config-tunnckocore", 3 | "tasks": { 4 | "build": [ 5 | "hela clean", 6 | "hela build:node" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 80, 4 | "semi": false, 5 | "useTabs": false, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "jsxBracketSameLine": true, 10 | "parser": "babylon" 11 | } 12 | -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | eslint: 3 | enabled: true 4 | duplication: 5 | enabled: true 6 | config: 7 | languages: 8 | - javascript 9 | checks: 10 | Similar code: 11 | enabled: false 12 | 13 | ratings: 14 | paths: 15 | - src/**/*.js 16 | 17 | exclude_paths: 18 | - src/cli.js 19 | - test/**/*.js 20 | - config/**/*.js 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | 4 | notifications: 5 | email: false 6 | 7 | cache: 8 | yarn: true 9 | directories: 10 | - node_modules 11 | 12 | node_js: 13 | - '8' 14 | - '6' 15 | 16 | os: linux 17 | 18 | before_install: 19 | - curl -o- -L https://yarnpkg.com/install.sh | bash 20 | - export PATH=$HOME/.yarn/bin:$PATH 21 | 22 | script: yarn test 23 | 24 | after_success: 25 | - bash <(curl -s https://codecov.io/bash) 26 | 27 | branches: 28 | except: 29 | - /^v\d+\.\d+\.\d+$/ 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: tunnckoCore 2 | 3 | # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 4 | custom: 5 | - https://gumroad.com/l/tunnckoCoreRecurringDonation 6 | 7 | # github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 8 | #open_collective: # Replace with a single Open Collective username 9 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 10 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 11 | #liberapay: # Replace with a single Liberapay username 12 | #issuehunt: # Replace with a single IssueHunt username 13 | #otechie: # Replace with a single Otechie username 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-present Charlike Mike Reagent 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Always-ignore dirs # 2 | # #################### 3 | _gh_pages 4 | node_modules 5 | jspm_packages 6 | bower_components 7 | vendor 8 | build 9 | dest 10 | dist 11 | lib-cov 12 | coverage 13 | .nyc_output 14 | nbproject 15 | cache 16 | temp 17 | tmp 18 | 19 | # npm >=5 lock file, we use Yarn! 20 | package-lock.json 21 | 22 | # Typescript v1 declaration files 23 | typings/ 24 | 25 | # Optional npm cache directory 26 | .npm 27 | 28 | # Packages # 29 | # ########## 30 | *.7z 31 | *.dmg 32 | *.iso 33 | *.jar 34 | *.rar 35 | *.tar 36 | *.zip 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # OS, Logs and databases # 42 | # ######################### 43 | logs 44 | *.log 45 | npm-debug.log* 46 | npm-debug.log* 47 | yarn-debug.log* 48 | yarn-error.log* 49 | *.dat 50 | *.sql 51 | *.sqlite 52 | *~ 53 | ~* 54 | 55 | # Runtime data 56 | pids 57 | *.pid 58 | *.seed 59 | *.pid.lock 60 | 61 | # Editors 62 | *.idea 63 | 64 | # Another files # 65 | # ############### 66 | Icon? 67 | .DS_Store* 68 | Thumbs.db 69 | ehthumbs.db 70 | Desktop.ini 71 | .directory 72 | ._* 73 | lcov.info 74 | 75 | # Runtime data 76 | pids 77 | *.pid 78 | *.seed 79 | *.pid.lock 80 | 81 | # Optional npm cache directory 82 | .npm 83 | 84 | # Optional REPL history 85 | .node_repl_history 86 | 87 | # Optional eslint cache 88 | .eslintcache 89 | 90 | # Yarn Integrity file 91 | .yarn-integrity 92 | 93 | # dotenv environment variables file 94 | .env 95 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Always-ignore dirs # 2 | # #################### 3 | _gh_pages 4 | node_modules 5 | jspm_packages 6 | bower_components 7 | vendor 8 | build 9 | dest 10 | dist 11 | lib-cov 12 | coverage 13 | .nyc_output 14 | nbproject 15 | cache 16 | temp 17 | tmp 18 | 19 | # npm >=5 lock file, we use Yarn! 20 | package-lock.json 21 | 22 | # Typescript v1 declaration files 23 | typings/ 24 | 25 | # Optional npm cache directory 26 | .npm 27 | 28 | # Packages # 29 | # ########## 30 | *.7z 31 | *.dmg 32 | *.iso 33 | *.jar 34 | *.rar 35 | *.tar 36 | *.zip 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # OS, Logs and databases # 42 | # ######################### 43 | logs 44 | *.log 45 | npm-debug.log* 46 | npm-debug.log* 47 | yarn-debug.log* 48 | yarn-error.log* 49 | *.dat 50 | *.sql 51 | *.sqlite 52 | *~ 53 | ~* 54 | 55 | # Runtime data 56 | pids 57 | *.pid 58 | *.seed 59 | *.pid.lock 60 | 61 | # Editors 62 | *.idea 63 | 64 | # Another files # 65 | # ############### 66 | Icon? 67 | .DS_Store* 68 | Thumbs.db 69 | ehthumbs.db 70 | Desktop.ini 71 | .directory 72 | ._* 73 | lcov.info 74 | 75 | # Runtime data 76 | pids 77 | *.pid 78 | *.seed 79 | *.pid.lock 80 | 81 | # Optional npm cache directory 82 | .npm 83 | 84 | # Optional REPL history 85 | .node_repl_history 86 | 87 | # Optional eslint cache 88 | .eslintcache 89 | 90 | # Yarn Integrity file 91 | .yarn-integrity 92 | 93 | # dotenv environment variables file 94 | .env 95 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "get-installed-path", 3 | "version": "0.0.0-semantic-release", 4 | "description": "Get installation path where the given package is installed. Works for globally and locally installed packages", 5 | "repository": "tunnckoCore/get-installed-path", 6 | "homepage": "https://github.com/tunnckoCore/get-installed-path", 7 | "author": "Charlike Mike Reagent <@tunnckoCore> (https://i.am.charlike.online)", 8 | "nspId": "976d071f-5f2e-4ca6-9583-8c2b9dbf6e76", 9 | "src": "./src/**/*.js", 10 | "main": "./dist/index.js", 11 | "module": "./dist/index.es.js", 12 | "scripts": { 13 | "start": "hela", 14 | "test": "yarn start test", 15 | "posttest": "rimraf dist/node_modules && rimraf dist/test.js", 16 | "precommit": "yarn start precommit", 17 | "commit": "yarn start commit" 18 | }, 19 | "license": "MIT", 20 | "licenseStart": 2016, 21 | "engines": { 22 | "node": ">=6", 23 | "npm": ">=5", 24 | "yarn": ">=1" 25 | }, 26 | "files": [ 27 | "dist/" 28 | ], 29 | "dependencies": { 30 | "global-modules": "2.0.0" 31 | }, 32 | "devDependencies": { 33 | "eslint-config-standard-tunnckocore": "1.0.10", 34 | "hela": "3.2.2", 35 | "hela-config-tunnckocore": "3.0.26", 36 | "husky": "4.2.3", 37 | "mkdirp": "1.0.3", 38 | "mukla": "0.4.9", 39 | "pkg-dir": "4.2.0", 40 | "rimraf": "3.0.2", 41 | "semantic-release": "17.0.4" 42 | }, 43 | "keywords": [ 44 | "filepath", 45 | "get", 46 | "global", 47 | "globally", 48 | "install", 49 | "installed", 50 | "local", 51 | "locally", 52 | "npm", 53 | "package", 54 | "path", 55 | "pkg", 56 | "resolve" 57 | ], 58 | "verb": { 59 | "run": true, 60 | "toc": { 61 | "render": true, 62 | "method": "preWrite", 63 | "maxdepth": 3 64 | }, 65 | "layout": "empty", 66 | "tasks": [ 67 | "readme" 68 | ], 69 | "related": { 70 | "list": [ 71 | "always-done", 72 | "minibase", 73 | "try-catch-core", 74 | "detect-installed", 75 | "is-installed", 76 | "global-modules", 77 | "global-prefix", 78 | "global-paths" 79 | ], 80 | "highlight": "detect-installed" 81 | }, 82 | "lint": { 83 | "reflinks": true 84 | }, 85 | "reflinks": [ 86 | "always-done", 87 | "async-done", 88 | "base", 89 | "charlike-cli", 90 | "dezalgo", 91 | "global-modules", 92 | "hela", 93 | "once", 94 | "prs-welcome-img", 95 | "prs-welcome-url" 96 | ] 97 | }, 98 | "release": { 99 | "analyzeCommits": "simple-commit-message" 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | # From v3, changes are in GitHub Releases page 6 | 7 | 8 | ## [2.1.1](https://github.com/tunnckoCore/get-installed-path/compare/v2.1.0...v2.1.1) (2017-08-22) 9 | 10 | 11 | ### Bug Fixes 12 | 13 | * **deps:** update deps, use eslint, add renovate config ([d1dbee3](https://github.com/tunnckoCore/get-installed-path/commit/d1dbee3)) 14 | 15 | 16 | 17 | 18 | # [2.1.0](https://github.com/tunnckoCore/get-installed-path/compare/v2.0.3...v2.1.0) (2017-08-22) 19 | 20 | 21 | ### Features 22 | 23 | * **recursion:** support path recursion via `options.paths` ([#13](https://github.com/tunnckoCore/get-installed-path/issues/13)) ([a70d67f](https://github.com/tunnckoCore/get-installed-path/commit/a70d67f)) 24 | 25 | 26 | 27 | 28 | ## [2.0.3](https://github.com/tunnckocore/get-installed-path/compare/v2.0.2...v2.0.3) (2016-12-12) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * **appveyor:** force install npm globally at install step ([06ca995](https://github.com/tunnckocore/get-installed-path/commit/06ca995)) 34 | 35 | 36 | 37 | 38 | ## [2.0.2](https://github.com/tunnckocore/get-installed-path/compare/v2.0.1...v2.0.2) (2016-12-11) 39 | 40 | 41 | ### Bug Fixes 42 | 43 | * **err:** fix to return rejected promise if exists but not a directory ([80a2b1e](https://github.com/tunnckocore/get-installed-path/commit/80a2b1e)) 44 | 45 | 46 | 47 | 48 | ## [2.0.1](https://github.com/tunnckocore/get-installed-path/compare/v2.0.0...v2.0.1) (2016-12-11) 49 | 50 | 51 | ### Bug Fixes 52 | 53 | * **package:** all coverage to 100 ([1343d90](https://github.com/tunnckocore/get-installed-path/commit/1343d90)) 54 | 55 | 56 | 57 | 58 | # [2.0.0](https://github.com/tunnckocore/get-installed-path/compare/v1.0.3...v2.0.0) (2016-12-11) 59 | 60 | 61 | ### Chores 62 | 63 | * **refactor:** update boilerplate, refactor ([970e833](https://github.com/tunnckocore/get-installed-path/commit/970e833)) 64 | 65 | 66 | ### BREAKING CHANGES 67 | 68 | * refactor: requires node >= 4; drop callback api - now is promise returning; expose .sync 69 | 70 | method 71 | 72 | 73 | 74 | 75 | 76 | ## 1.0.3 - 2015-07-17 77 | - Release v1.0.3 / npm@v1.0.3 78 | - add callback api, close #2 79 | - update boilerplate 80 | 81 | ## 1.0.2 - 2015-05-06 82 | - Release v1.0.2 / npm@v1.0.2 83 | - standard style for the example usage 84 | - plus some tweaks 85 | 86 | ## 1.0.1 - 2015-05-06 87 | - Release v1.0.1 / npm@v1.0.1 88 | - add related section, close #1 89 | - update badges, close #1 90 | - rename some files to draw attention, close #1 91 | - update code style - apply feross/standard, close #1 92 | 93 | ## 1.0.0 - 2015-04-18 94 | - Release v1.0.0 / npm@v1.0.0 95 | - run keywords(1) 96 | - add usage example 97 | 98 | ## 0.0.0 - 2015-04-18 99 | - first commits -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at `open.source.charlike@gmail.com` mail address. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | import modules from 'global-modules' 4 | 5 | /** 6 | * > Get installed path of globally or locally `name` package. 7 | * By default it checks if `name` exists as directory in [global-modules][] 8 | * directory of the system. Pass `opts.local` to get path of `name` 9 | * package from local directory or from `opts.cwd`. Returns rejected 10 | * promise if module not found in global/local `node_modules` folder or 11 | * if it exist but is not a directory. 12 | * 13 | * @example 14 | * const { getInstalledPath } = require('get-installed-path') 15 | * 16 | * getInstalledPath('npm').then((path) => { 17 | * console.log(path) 18 | * // => '/home/charlike/.nvm/path/to/lib/node_modules/npm' 19 | * }) 20 | * 21 | * getInstalledPath('foo-bar-barwerwlekrjw').catch((err) => { 22 | * console.log(err.message) 23 | * // => 'module not found "foo-bar-barwerwlekrjw" in path ...' 24 | * }) 25 | * 26 | * getInstalledPath('npm', { 27 | * local: true 28 | * }).catch((err) => { 29 | * console.log(err.message) 30 | * // => 'module not found "foo-bar-barwerwlekrjw" in path ...' 31 | * }) 32 | * 33 | * getInstalledPath('global-modules', { 34 | * local: true 35 | * }).then((path) => { 36 | * console.log(path) 37 | * // => '~/code/get-installed-path/node_modules/global-modules' 38 | * }) 39 | * 40 | * // If you are using it for some sub-directory 41 | * // pass `opts.cwd` to be where the `node_modules` 42 | * // folder is. 43 | * process.chidr('foo-bar-baz') 44 | * getInstalledPath('global-modules', { 45 | * local: true, 46 | * cwd: '../' 47 | * }).then((path) => { 48 | * console.log(path) 49 | * // => '~/code/get-installed-path/node_modules/global-modules' 50 | * }) 51 | * 52 | * // When searching for the path of a package that is required 53 | * // by several other packages, its path may not be in the 54 | * // closest node_modules. In this case, to search recursively, 55 | * // you can use the following: 56 | * getInstalledPath('npm', { 57 | * paths: process.mainModule.paths 58 | * }).then((path) => { 59 | * // ... 60 | * }) 61 | * // `process.mainModule` refers to the location of the current 62 | * // entry script. 63 | * 64 | * @param {string} name package name 65 | * @param {Object} opts pass `opts.local` to check locally 66 | * @return {Promise} rejected promise if `name` not a string or is empty string 67 | * @name getInstalledPath 68 | * @public 69 | */ 70 | function getInstalledPath (name, opts) { 71 | return new Promise((resolve, reject) => { 72 | if (!isValidString(name)) { 73 | const message = 'get-installed-path: expect `name` to be string' 74 | return reject(new TypeError(message)) 75 | } 76 | 77 | const targetPaths = defaults(name, opts) 78 | const statPath = (filepath) => 79 | fs.stat(filepath, (e, stats) => { 80 | if (e && targetPaths.length > 0) { 81 | statPath(targetPaths.shift()) 82 | return 83 | } else if (e) { 84 | const label = 'get-installed-path:' 85 | const msg = `${label} module not found "${name}" in path ${filepath}` 86 | return reject(new Error(msg)) 87 | } 88 | 89 | if (stats.isDirectory()) { 90 | return resolve(filepath) 91 | } 92 | 93 | const msg = `Possibly "${name}" is not a directory: ${filepath}` 94 | let err = new Error('get-installed-path: some error occured! ' + msg) 95 | reject(err) 96 | }) 97 | statPath(targetPaths.shift()) 98 | }) 99 | } 100 | 101 | /** 102 | * > Get installed path of a `name` package synchronous. 103 | * Returns `boolean` when `paths` option is used and filepath is directory, 104 | * otherwise returns a full filepath OR throws error. 105 | * 106 | * @example 107 | * const { getInstalledPathSync } = require('get-installed-path') 108 | * 109 | * const npmPath = getInstalledPathSync('npm') 110 | * console.log(npmPath) 111 | * // => '/home/charlike/.nvm/path/to/lib/node_modules/npm' 112 | * 113 | * const gmPath = getInstalledPathSync('global-modules', { local: true }) 114 | * console.log(gmPath) 115 | * // => '~/code/get-installed-path/node_modules/global-modules' 116 | * 117 | * @param {string} name package name 118 | * @param {Object} opts pass `opts.local` to check locally 119 | * @return {string} The full filepath or throw `TypeError` if `name` not a string or is empty string 120 | * @name getInstalledPathSync 121 | * @public 122 | */ 123 | function getInstalledPathSync (name, opts) { 124 | if (!isValidString(name)) { 125 | throw new TypeError('get-installed-path: expect `name` to be string') 126 | } 127 | 128 | const filePaths = defaults(name, opts) 129 | const firstPath = filePaths[0] 130 | const modulePath = filePaths.find((filePath) => { 131 | let stat = null 132 | 133 | try { 134 | stat = fs.statSync(filePath) 135 | } catch (e) { 136 | return false 137 | } 138 | 139 | if (stat.isDirectory()) { 140 | return true 141 | } 142 | 143 | const msg = `Possibly "${name}" is not a directory: ${filePath}` 144 | throw new Error('get-installed-path: some error occured! ' + msg) 145 | }) 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 | 153 | return modulePath 154 | } 155 | 156 | function isValidString (val) { 157 | return typeof val === 'string' ? val.length > 0 : false 158 | } 159 | 160 | function defaults (name, opts) { 161 | opts = opts && typeof opts === 'object' ? opts : {} 162 | opts.cwd = typeof opts.cwd === 'string' ? opts.cwd : process.cwd() 163 | if (opts.paths) { 164 | return opts.paths.map((modulePath) => path.join(modulePath, name)) 165 | } else if (opts.local) { 166 | return [path.join(opts.cwd, 'node_modules', name)] 167 | } 168 | return [path.join(modules, name)] 169 | } 170 | 171 | export { getInstalledPath, getInstalledPathSync } 172 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide :100: 2 | 3 | > _Hello stranger! :sparkles: Please, read the [Code Of Conduct](./CODE_OF_CONDUCT.md) and the full guide at 4 | [tunnckoCore/contributing](https://github.com/tunnckoCore/contributing)! 5 | > Even if you are an experienced developer or active open source maintainer, it worth look over there._ 6 | 7 | ![welcome-teal](https://cloud.githubusercontent.com/assets/194400/22215755/76cb4dbc-e194-11e6-95ed-7def95e68f14.png) 8 | 9 | > “_Every thought, **every word**, and **every action** 10 | that **adds to** the **positive** is a **contribution to peace**.
11 | Each and **every one** of us is **capable** of making such a **contribution**_.” 12 | ~ [Aung San Suu Kyi](https://en.wikipedia.org/wiki/Aung_San_Suu_Kyi) 13 | 14 | Firstly, a ***heartfelt thank you*** for making time to contribute to this project!
15 | 16 | 17 | 18 | ## Are you new to Open Source? 19 | 20 | If you’re a **new** open source contributor, the process can be intimidating. 21 | _What if you don’t know how to code?_ What if something goes wrong? **Don't worry!** 22 | 23 | **You don’t have to contribute code!** A common misconception about contributing to open source is that you need 24 | to _contribute code_. In fact, it’s often the other parts of a project that are most neglected or overlooked. 25 | You’ll do the project a _huge favor_ by offering to pitch in with these types of **contributions**! 26 | 27 | **Even if you like to write code**, other types of contributions are a great way to get involved with a project 28 | and meet other community members. Building those relationships will give you opportunities to work on other parts 29 | of the project. 30 | 31 | - **Yes:** [Step to the full guide](https://github.com/tunnckoCore/contributing) if you are _new_, **super 32 | curious** _OR_ if you're **really really new** and need more depth. 33 | - **No:** Then continue reading, if you **know** for _what is all that_ or you're **familiar** with 34 | [@tunnckoCore](https://github.com/tunnckoCore) projects. 35 | 36 | 37 | 38 | ## Opening an issue 39 | 40 | You should usually open an issue in the following situations: 41 | 42 | - Report an error you can't solve yourself 43 | - Discuss a high-level topic or idea (ex. community, vision, policies) 44 | - Propose a new feature or other project idea 45 | 46 | ### Tips for communicating on issues: 47 | 48 | - **If you see an open issue that you want to tackle,** comment on the issue to let people know you're on it. 49 | That way, people are less likely to duplicate your work. 50 | - **If an issue was opened a while ago,** it's possible that it's being addressed somewhere else, or has already 51 | been resolved, so comment to ask for confirmation before starting work. 52 | - **If you opened an issue, but figured out the answer later on your own,** comment on the issue to let people 53 | know, then close the issue. Even documenting that outcome is a contribution to the project. 54 | - **Please be patient** and _wait_ for a response from the maintainer or somebody else. Check out [_"What to do 55 | next?"_](https://github.com/tunnckoCore/contributing#what-can-i-do-while-im-waiting). 56 | 57 | ### Include Any/All _Relevant_ Information in the _Issue Description_ 58 | 59 | - Please _include_ as much ***relevant information*** as you can, such as versions and operating system. 60 | - A _good_ issue _describes_ the idea in a _**concise** and **user-focused**_ way. 61 | - ***Never*** leave the issue _description_ blank even when you are in a "rush" - the point of an issue is to 62 | _communicate_. 63 | 64 | **Why can't the description be empty?** You _wouldn't_ send a _blank email_ to hundreds of your friends (_unless 65 | you wanted to freak them out!_), right? Submitting _blank issues_ is doing **exactly** that! It sends a ["_I have 66 | **no idea** what I'm doing_"](https://www.google.com/search?q=i+have+no+idea+what+i%27m+doing&tbm=isch) 67 | **message** to your _peers_. 68 | 69 | 70 | 71 | ## Opening a pull request 72 | 73 | > _If this is your first pull request, check out [Make a Pull Request](http://makeapullrequest.com/) by 74 | [**@kentcdodds**](https://github.com/kentcdodds)._ 75 | 76 | ![get-it-done](https://cloud.githubusercontent.com/assets/194400/22265743/44a2ca72-e275-11e6-819d-2c5a1958ea11.png) 77 | 78 | You should usually open a pull request in the following situations: 79 | 80 | - Submit trivial fixes (ex. a typo, broken link, or obvious error) 81 | - Start work on a contribution that was already asked for, or that you've already discussed, in an issue 82 | 83 | A pull request doesn't have to represent finished work. It's usually better to open a pull request early on, so 84 | others can watch or give feedback on your progress. Just mark it as a "WIP" (Work in Progress) in the subject 85 | line. You can always add more commits later. 86 | 87 | ### Pro Tips to follow 88 | 89 | - **Don't worry about the style** because we use [StandardJS](https://github.com/standard/standard), 90 | [ESLint](https://github.com/eslint/eslint) and [Prettier](https://github.com/prettier/prettier). Use the `npm run 91 | lint` command. 92 | - **Don't change the markdown files**, because the README is generated (it isn't hand written) and the API 93 | section is from JSDoc code comments. Leave this step to us when, _and if_, the pull request is merged. 94 | - **Don't comment out tests**, instead use `test.skip`. They'll still be shown in the output, but are never run. 95 | 96 | ### How to submit a pull request 97 | 98 | There are just **8 easy steps** you should do. _**Please**_, follow them in _that exact_ order. 99 | 100 | 1. **[Fork the repository](https://guides.github.com/activities/forking/)** and clone it locally. 101 | 2. **[Create a branch](https://guides.github.com/introduction/flow/)** for your edits. 102 | 3. **Install dependencies** by running the `npm install` command. 103 | 4. **Test if everything is working** before you start _doing anything_ with the `npm test` command. If something 104 | is wrong, please report it first and don't continue if you can't skip the problem easily. 105 | 5. **Reference any relevant issues**, supporting documentation or information in your PR (ex. "Closes #37.") 106 | 6. **Test again or add new ones!** Run `npm test` again to _make sure_ your changes don't break existing tests. 107 | 7. **Commit your changes** by running `npm run commit`. It _will lead you_ through what the commit message 108 | _should look like_ and will run more tasks **to ensure** that code style and tests are okey. 109 | 8. **Wait response!** What to do in that time? Check out [_**"What to do 110 | next?"**_](https://github.com/tunnckoCore/contributing#what-can-i-do-while-im-waiting). 111 | 112 | :star: **You did it**! :star: _Congratulations on becoming one of the [Open Source](https://opensource.guide) 113 | contributors!_ 114 | 115 | ![thank-you-green-large](https://cloud.githubusercontent.com/assets/194400/22229077/5b0695ee-e1cd-11e6-9001-e5ff53afce36.jpg) 116 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Charlike Mike Reagent 3 | * @copyright 2016-present @tunnckoCore/team and contributors 4 | * @license MIT 5 | */ 6 | 7 | /* eslint-disable max-len */ 8 | 9 | import fs from 'fs' 10 | import path from 'path' 11 | import test from 'mukla' 12 | import mkdirp from 'mkdirp' 13 | import getDir from 'pkg-dir' 14 | import rimraf from 'rimraf' 15 | 16 | import { getInstalledPath, getInstalledPathSync } from '../src/index.js' 17 | 18 | test('async: return rejected promise if exists but not a directory', async () => { 19 | fs.writeFileSync('./node_modules/foo-j4hbar-quxieiisas', 'xxxyyzzz') 20 | 21 | try { 22 | await getInstalledPath('foo-j4hbar-quxieiisas', { 23 | local: true, 24 | }) 25 | } catch (err) { 26 | test.strictEqual(/some error occured/.test(err.message), true) 27 | test.strictEqual(/Possibly "foo-j4hbar-quxieiisas"/.test(err.message), true) 28 | test.strictEqual(/is not a directory/.test(err.message), true) 29 | rimraf.sync('./node_modules/foo-j4hbar-quxieiisas') 30 | } 31 | }) 32 | 33 | test('sync: should throw if exists but not a directory', (done) => { 34 | function fixture () { 35 | fs.writeFileSync('./node_modules/aaaaa-xxx-x-sasas', 'abc') 36 | getInstalledPathSync('aaaaa-xxx-x-sasas', { local: true }) 37 | } 38 | 39 | test.throws(fixture, Error) 40 | test.throws(fixture, /Possibly "aaaaa-xxx-x-sasas" is not a directory/) 41 | test.throws(fixture, /some error occured/) 42 | rimraf.sync('./node_modules/aaaaa-xxx-x-sasas') 43 | done() 44 | }) 45 | 46 | test('async: should get TypeError when invalid `name` is passed', async () => { 47 | try { 48 | await getInstalledPath(1234) 49 | } catch (err) { 50 | test.strictEqual(err.name, 'TypeError') 51 | test.strictEqual(/expect `name` to be string/.test(err.message), true) 52 | } 53 | }) 54 | 55 | test('async: should return absolute path if exists globally', async () => { 56 | const fp = await getInstalledPath('npm') 57 | 58 | test.strictEqual(/node_modules/.test(fp), true) 59 | test.strictEqual(/npm/.test(fp), true) 60 | }) 61 | 62 | test('async: should return Error if not exists glboally', async () => { 63 | try { 64 | await getInstalledPath('foo-bar-bqwewrwevdfg-sa') 65 | } catch (err) { 66 | test.strictEqual(/module not found/.test(err.message), true) 67 | test.strictEqual( 68 | /"foo-bar-bqwewrwevdfg-sa" in path/.test(err.message), 69 | true 70 | ) 71 | } 72 | }) 73 | 74 | test('async: should return absolute path if exists locally', async () => { 75 | const fp = await getInstalledPath('global-modules', { 76 | local: true, 77 | }) 78 | 79 | test.strictEqual(/get-installed-path/.test(fp), true) 80 | test.strictEqual(/node_modules/.test(fp), true) 81 | test.strictEqual(/global-modules/.test(fp), true) 82 | }) 83 | 84 | test('async: should return Error if not exists locally', async () => { 85 | try { 86 | await getInstalledPath('sdfjkhskh3-sf9sd78fsdf', { 87 | local: true, 88 | }) 89 | } catch (err) { 90 | test.strictEqual(/module not found/.test(err.message), true) 91 | test.strictEqual(/"sdfjkhskh3-sf9sd78fsdf" in path/.test(err.message), true) 92 | test.strictEqual(/get-installed-path/.test(err.message), true) 93 | test.strictEqual(/node_modules/.test(err.message), true) 94 | } 95 | }) 96 | 97 | /** 98 | * testing synchronous mode 99 | */ 100 | 101 | test('sync: throw TypeError when invalid `name` is passed', (done) => { 102 | function fixture () { 103 | getInstalledPathSync(1234) 104 | } 105 | 106 | test.throws(fixture, TypeError) 107 | test.throws(fixture, /expect `name` to be string/) 108 | done() 109 | }) 110 | 111 | test('synchronous: should return absolute path if exists globally', (done) => { 112 | const fp = getInstalledPathSync('npm') 113 | 114 | test.strictEqual(/node_modules/.test(fp), true) 115 | test.strictEqual(/npm/.test(fp), true) 116 | done() 117 | }) 118 | 119 | test('synchronous: should throw Error if not exists globally', (done) => { 120 | function fixture () { 121 | getInstalledPathSync('foo-bar-bqwewrwevdfg-sa') 122 | } 123 | 124 | test.throws(fixture, Error) 125 | test.throws(fixture, /module not found/) 126 | test.throws(fixture, /"foo-bar-bqwewrwevdfg-sa" in path/) 127 | test.throws(fixture, /node_modules/) 128 | done() 129 | }) 130 | 131 | test('synchronous: should return absolute path if exists locally', (done) => { 132 | const filepath = getInstalledPathSync('global-modules', { 133 | local: true, 134 | }) 135 | test.strictEqual(/get-installed-path/.test(filepath), true) 136 | test.strictEqual(/node_modules/.test(filepath), true) 137 | test.strictEqual(/global-modules/.test(filepath), true) 138 | done() 139 | }) 140 | 141 | test('synchronous: should throw Error if not exists locally', (done) => { 142 | function fixture () { 143 | getInstalledPathSync('sdfjkhskh3-sf9sd78fsdf', { 144 | local: true, 145 | }) 146 | } 147 | 148 | test.throws(fixture, Error) 149 | test.throws(fixture, /module not found "sdfjkhskh3-sf9sd78fsdf"/) 150 | test.throws(fixture, /in path.*node_modules/) 151 | done() 152 | }) 153 | 154 | test('sync: should work for subdirs (issue #5), exists locally', (done) => { 155 | const dirname = __dirname 156 | mkdirp.sync('barrr') 157 | process.chdir('barrr') 158 | 159 | const filepath = getInstalledPathSync('global-modules', { 160 | cwd: getDir.sync(), 161 | local: true, 162 | }) 163 | 164 | test.strictEqual(/node_modules/.test(filepath), true) 165 | test.strictEqual(/global-modules/.test(filepath), true) 166 | 167 | process.chdir(dirname) 168 | rimraf.sync('barrr') 169 | done() 170 | }) 171 | 172 | test('async: should work for #5, not exists locally', async () => { 173 | const dirname = __dirname 174 | mkdirp.sync('subdir') 175 | process.chdir('subdir') 176 | 177 | try { 178 | await getInstalledPath('npm', { 179 | cwd: getDir.sync(), 180 | local: true, 181 | }) 182 | } catch (err) { 183 | test.strictEqual(/module not found "npm" in path/.test(err.message), true) 184 | 185 | process.chdir(dirname) 186 | rimraf.sync('subdir') 187 | } 188 | }) 189 | 190 | test('async: should support recursing directories (#11)', async () => { 191 | const targetModuleDir = path.resolve( 192 | __dirname, 193 | './node_modules/target-module' 194 | ) 195 | const testModuleDir = path.resolve(__dirname, './node_modules/test-module') 196 | 197 | mkdirp.sync(targetModuleDir) 198 | mkdirp.sync(path.resolve(testModuleDir, './node_modules')) 199 | 200 | fs.writeFileSync( 201 | path.resolve(targetModuleDir, './package.json'), 202 | JSON.stringify({ name: 'target-module' }) 203 | ) 204 | 205 | const fp = await getInstalledPath('target-module', { 206 | paths: [ 207 | path.resolve(testModuleDir, './node_modules'), 208 | path.resolve(__dirname, './node_modules'), 209 | ], 210 | }) 211 | 212 | test.strictEqual(/\/node_modules\/target-module/.test(fp), true) 213 | }) 214 | 215 | test('synchronous: should support recursing directories (#11)', () => { 216 | const targetModuleDir = path.resolve( 217 | __dirname, 218 | './node_modules/target-module' 219 | ) 220 | const testModuleDir = path.resolve(__dirname, './node_modules/test-module') 221 | 222 | mkdirp.sync(targetModuleDir) 223 | mkdirp.sync(path.resolve(testModuleDir, './node_modules')) 224 | 225 | fs.writeFileSync( 226 | path.resolve(targetModuleDir, './package.json'), 227 | JSON.stringify({ name: 'target-module' }) 228 | ) 229 | 230 | const filepath = getInstalledPathSync('target-module', { 231 | paths: [ 232 | path.resolve(testModuleDir, './node_modules'), 233 | path.resolve(__dirname, './node_modules'), 234 | ], 235 | }) 236 | 237 | test.strictEqual(/\/node_modules\/target-module/.test(filepath), true) 238 | }) 239 | -------------------------------------------------------------------------------- /.verb.md: -------------------------------------------------------------------------------- 1 | # {%= name %} [![npm version][npmv-img]][npmv-url] [![github release][github-release-img]][github-release-url] [![mit License][license-img]][license-url] [![NPM Downloads Total][downloads-total-img]][npmv-url] 2 | 3 | 6 | 7 | > {%= description %} 8 | 9 |
10 | 11 | {%= include('highlight') %} 12 | 13 | ## Quality Assurance :100: 14 | 15 | [![Code Climate][codeclimate-img]][codeclimate-url] 16 | [![Code Style Standard][standard-img]][standard-url] 17 | [![Linux Build][travis-img]][travis-url] 18 | [![Code Coverage][codecov-img]][codecov-url] 19 | [![Dependencies Status][dependencies-img]][dependencies-url] 20 | [![Renovate App Status][renovate-img]][renovate-url] 21 | [![Node Version Required][nodeversion-img]][nodeversion-url] 22 | 23 | If you have any _how-to_ kind of questions, please read [Code of Conduct](./CODE_OF_CONDUCT.md) and **join the chat** room or [open an issue][open-issue-url]. 24 | You may also read the [Contributing Guide](./CONTRIBUTING.md). There, beside _"How to contribute?"_, we describe everything **_stated_** by the badges. 25 | 26 | [![tunnckoCore support][chat-img]][chat-url] 27 | [![Code Format Prettier][prettier-img]][prettier-url] 28 | [![Node Security Status][nodesecurity-img]][nodesecurity-url] 29 | [![Conventional Commits][ccommits-img]][ccommits-url] 30 | [![Semantic Release][semantic-release-img]][semantic-release-url] 31 | [![First Timers Only][first-timers-only-img]][first-timers-only-url] 32 | 33 | 34 | Sponsor 36 | 37 |
38 |
39 | 40 | [![All Contributors Spec][all-contributors-img]](#contributors) 41 | [![Make A Pull Request][prs-welcome-img]][prs-welcome-url] 42 | [![Newsletter Subscribe][tinyletter-img]][tinyletter-url] 43 | [![PayPal Author Support][paypal-donate-img]][paypal-donate-url] 44 | [![Share Love][share-love-img]][share-love-url] 45 | [![BitHound Code][bithound-code-img]][bithound-code-url] 46 | 47 | ## Table of Contents 48 | 49 | 50 | ## Install 51 | 52 | This project requires [**Node.js**][nodeversion-url] **v{%= engines.node.slice(2) %}** and above. Use [**yarn**](https://yarnpkg.com) **v{%= engines.yarn.slice(2) %}** / [**npm**](https://www.npmjs.com) **v{%= engines.npm.slice(2) %}** or above to install it. 53 | 54 | ``` 55 | $ yarn add {%= name %} 56 | ``` 57 | 58 | ## API 59 | Review carefully the provided examples and the working [tests](./test/index.js). 60 | 61 | {%= apidocs('src/index.js') %} 62 | 63 | **[back to top](#thetop)** 64 | 65 | {% if (verb.related && verb.related.list && verb.related.list.length) { %} 66 | ## Related 67 | {%= related(verb.related.list, { words: 12 }) %} 68 | {% } %} 69 | 70 | **[back to top](#thetop)** 71 | 72 | ## Contributing 73 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue][open-issue-url]. 74 | Please read the [Contributing Guide](./CONTRIBUTING.md) and [Code of Conduct](./CODE_OF_CONDUCT.md) documents for advices. 75 | 76 | ## Author 77 | - [github/tunnckoCore](https://github.com/tunnckoCore) 78 | - [twitter/tunnckoCore](https://twitter.com/tunnckoCore) 79 | - [codementor/tunnckoCore](https://codementor.io/tunnckoCore) 80 | 81 | ## License 82 | {%= copyright({ start: licenseStart, linkify: true, prefix: 'Copyright', symbol: '©' }) %} {%= licenseStatement %} 83 | 84 | *** 85 | 86 | {%= include('footer') %} 87 | Project scaffolded and managed with [hela][]. 88 | 89 | {%= reflinks(verb.reflinks) %} 90 | 91 | 92 | 93 | [npmv-url]: https://www.npmjs.com/package/{%= name %} 94 | [npmv-img]: https://img.shields.io/npm/v/{%= name %}.svg?label=npm%20version 95 | 96 | [open-issue-url]: https://github.com/{%= repository %}/issues/new 97 | [github-release-url]: https://github.com/{%= repository %}/releases/latest 98 | [github-release-img]: https://img.shields.io/github/release/{%= repository %}.svg?label=github%20release 99 | 100 | [license-url]: https://github.com/{%= repository %}/blob/master/LICENSE 101 | [license-img]: https://img.shields.io/npm/l/{%= name %}.svg 102 | 103 | [downloads-weekly-img]: https://img.shields.io/npm/dw/{%= name %}.svg 104 | [downloads-monthly-img]: https://img.shields.io/npm/dm/{%= name %}.svg 105 | [downloads-total-img]: https://img.shields.io/npm/dt/{%= name %}.svg 106 | 107 | 108 | [codeclimate-url]: https://codeclimate.com/github/{%= repository %} 109 | [codeclimate-img]: https://img.shields.io/codeclimate/github/{%= repository %}.svg 110 | 111 | [standard-url]: https://github.com/standard/standard 112 | [standard-img]: https://img.shields.io/badge/code_style-standard-brightgreen.svg 113 | 114 | [travis-url]: https://travis-ci.org/{%= repository %} 115 | [travis-img]: https://img.shields.io/travis/{%= repository %}/master.svg?label=linux 116 | 117 | [codecov-url]: https://codecov.io/gh/{%= repository %} 118 | [codecov-img]: https://img.shields.io/codecov/c/github/{%= repository %}/master.svg 119 | 120 | [dependencies-url]: https://david-dm.org/{%= repository %} 121 | [dependencies-img]: https://img.shields.io/david/{%= repository %}.svg 122 | 123 | [renovate-url]: https://renovateapp.com 124 | [renovate-img]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg 125 | 126 | 127 | 128 | [chat-url]: https://tunnckocore.flock.com/?i=cx2xoeofjtj6eo6c 129 | [chat-img]: https://img.shields.io/badge/chat-on_flock-brightgreen.svg 130 | 131 | [prettier-url]: https://github.com/prettier/prettier 132 | [prettier-img]: https://img.shields.io/badge/styled_with-prettier-f952a5.svg 133 | 134 | [nodesecurity-url]: https://nodesecurity.io/orgs/tunnckocore-dev/projects/{%= nspId %} 135 | [nodesecurity-img]: https://nodesecurity.io/orgs/tunnckocore-dev/projects/{%= nspId %}/badge 136 | 138 | 139 | [semantic-release-url]: https://github.com/semantic-release/semantic-release 140 | [semantic-release-img]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 141 | 142 | [ccommits-url]: https://conventionalcommits.org/ 143 | [ccommits-img]: https://img.shields.io/badge/conventional_commits-1.0.0-yellow.svg 144 | 145 | [nodeversion-url]: https://nodejs.org/en/download 146 | [nodeversion-img]: https://img.shields.io/node/v/{%= name %}.svg 147 | 148 | [first-timers-only-img]: https://img.shields.io/badge/first--timers--only-friendly-blue.svg 149 | [first-timers-only-url]: http://www.firsttimersonly.com 150 | 151 | [prs-welcome-img]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg 152 | [prs-welcome-url]: http://makeapullrequest.com 153 | 154 | [all-contributors-img]: https://img.shields.io/github/contributors/{%= repository %}.svg?label=all%20contributors&colorB=ffa500 155 | 156 | [bithound-deps-url]: https://www.bithound.io/github/{%= repository %}/master/dependencies/npm 157 | [bithound-deps-img]: https://www.bithound.io/github/{%= repository %}/badges/dependencies.svg 158 | 159 | [bithound-code-url]: https://www.bithound.io/github/{%= repository %}/master 160 | [bithound-code-img]: https://www.bithound.io/github/{%= repository %}/badges/code.svg 161 | 162 | [paypal-donate-url]: https://paypal.me/tunnckoCore/10 163 | [paypal-donate-img]: https://img.shields.io/badge/paypal-donate-009cde.svg 164 | 165 | [tinyletter-url]: https://tinyletter.com/tunnckoCore 166 | [tinyletter-img]: https://img.shields.io/badge/newsletter-subscribe-9caaf8.svg 167 | 168 | [share-love-url]: https://twitter.com/intent/tweet?text={%= encodeURI(homepage) %}&via=tunnckoCore 169 | [share-love-img]: https://img.shields.io/badge/share-♥-ed1c24.svg 170 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # get-installed-path [![npm version][npmv-img]][npmv-url] [![github release][github-release-img]][github-release-url] [![mit License][license-img]][license-url] [![NPM Downloads Total][downloads-total-img]][npmv-url] 2 | 3 | 6 | 7 | > Get installation path where the given package is installed. Works for globally and locally installed packages 8 | 9 |
10 | 11 | You might also be interested in [detect-installed](https://github.com/tunnckocore/detect-installed#readme). 12 | 13 | ## Quality Assurance :100: 14 | 15 | [![Code Climate][codeclimate-img]][codeclimate-url] 16 | [![Code Style Standard][standard-img]][standard-url] 17 | [![Linux Build][travis-img]][travis-url] 18 | [![Code Coverage][codecov-img]][codecov-url] 19 | [![Dependencies Status][dependencies-img]][dependencies-url] 20 | [![Renovate App Status][renovate-img]][renovate-url] 21 | [![Node Version Required][nodeversion-img]][nodeversion-url] 22 | 23 | If you have any _how-to_ kind of questions, please read [Code of Conduct](./CODE_OF_CONDUCT.md) and **join the chat** room or [open an issue][open-issue-url]. 24 | You may also read the [Contributing Guide](./CONTRIBUTING.md). There, beside _"How to contribute?"_, we describe everything **_stated_** by the badges. 25 | 26 | [![tunnckoCore support][chat-img]][chat-url] 27 | [![Code Format Prettier][prettier-img]][prettier-url] 28 | [![Node Security Status][nodesecurity-img]][nodesecurity-url] 29 | [![Conventional Commits][ccommits-img]][ccommits-url] 30 | [![Semantic Release][semantic-release-img]][semantic-release-url] 31 | [![First Timers Only][first-timers-only-img]][first-timers-only-url] 32 | 33 | 34 | [![All Contributors Spec][all-contributors-img]](#contributors) 35 | [![Make A Pull Request][prs-welcome-img]][prs-welcome-url] 36 | [![Newsletter Subscribe][tinyletter-img]][tinyletter-url] 37 | [![PayPal Author Support][paypal-donate-img]][paypal-donate-url] 38 | [![Share Love][share-love-img]][share-love-url] 39 | [![BitHound Code][bithound-code-img]][bithound-code-url] 40 | 41 | ## Table of Contents 42 | - [Install](#install) 43 | - [API](#api) 44 | * [getInstalledPath](#getinstalledpath) 45 | * [getInstalledPathSync](#getinstalledpathsync) 46 | - [Related](#related) 47 | - [Contributing](#contributing) 48 | - [Author](#author) 49 | - [License](#license) 50 | 51 | _(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_ 52 | 53 | ## Install 54 | 55 | This project requires [**Node.js**][nodeversion-url] **v6** and above. Use [**yarn**](https://yarnpkg.com) **v1** / [**npm**](https://www.npmjs.com) **v5** or above to install it. 56 | 57 | ``` 58 | $ yarn add get-installed-path 59 | ``` 60 | 61 | ## API 62 | Review carefully the provided examples and the working [tests](./test/index.js). 63 | 64 | ### [getInstalledPath](src/index.js#L71) 65 | 66 | > Get installed path of globally or locally `name` package. 67 | By default it checks if `name` exists as directory in [global-modules][] 68 | directory of the system. Pass `opts.local` to get path of `name` 69 | package from local directory or from `opts.cwd`. Returns rejected 70 | promise if module not found in global/local `node_modules` folder or 71 | if it exist but is not a directory. 72 | 73 | **Params** 74 | 75 | * `name` **{string}**: package name 76 | * `opts` **{Object}**: pass `opts.local` to check locally 77 | * `returns` **{Promise}**: rejected promise if `name` not a string or is empty string 78 | 79 | **Example** 80 | 81 | ```jsx 82 | const { getInstalledPath } = require('get-installed-path') 83 | 84 | getInstalledPath('npm').then((path) => { 85 | console.log(path) 86 | // => '/home/charlike/.nvm/path/to/lib/node_modules/npm' 87 | }) 88 | 89 | getInstalledPath('foo-bar-barwerwlekrjw').catch((err) => { 90 | console.log(err.message) 91 | // => 'module not found "foo-bar-barwerwlekrjw" in path ...' 92 | }) 93 | 94 | getInstalledPath('npm', { 95 | local: true 96 | }).catch((err) => { 97 | console.log(err.message) 98 | // => 'module not found "foo-bar-barwerwlekrjw" in path ...' 99 | }) 100 | 101 | getInstalledPath('global-modules', { 102 | local: true 103 | }).then((path) => { 104 | console.log(path) 105 | // => '~/code/get-installed-path/node_modules/global-modules' 106 | }) 107 | 108 | // If you are using it for some sub-directory 109 | // pass `opts.cwd` to be where the `node_modules` 110 | // folder is. 111 | process.chidr('foo-bar-baz') 112 | getInstalledPath('global-modules', { 113 | local: true, 114 | cwd: '../' 115 | }).then((path) => { 116 | console.log(path) 117 | // => '~/code/get-installed-path/node_modules/global-modules' 118 | }) 119 | 120 | // When searching for the path of a package that is required 121 | // by several other packages, its path may not be in the 122 | // closest node_modules. In this case, to search recursively, 123 | // you can use the following: 124 | getInstalledPath('npm', { 125 | paths: process.mainModule.paths 126 | }).then((path) => { 127 | // ... 128 | }) 129 | // `process.mainModule` refers to the location of the current 130 | // entry script. 131 | ``` 132 | 133 | ### [getInstalledPathSync](src/index.js#L124) 134 | 135 | > Get installed path of a `name` package synchronous. 136 | Returns `boolean` when `paths` option is used and filepath is directory, 137 | otherwise returns a full filepath OR throws error. 138 | 139 | **Params** 140 | 141 | * `name` **{string}**: package name 142 | * `opts` **{Object}**: pass `opts.local` to check locally 143 | * `returns` **{string}**: The full filepath or throw `TypeError` if `name` not a string or is empty string 144 | 145 | **Example** 146 | 147 | ```jsx 148 | const { getInstalledPathSync } = require('get-installed-path') 149 | 150 | const npmPath = getInstalledPathSync('npm') 151 | console.log(npmPath) 152 | // => '/home/charlike/.nvm/path/to/lib/node_modules/npm' 153 | 154 | const gmPath = getInstalledPathSync('global-modules', { local: true }) 155 | console.log(gmPath) 156 | // => '~/code/get-installed-path/node_modules/global-modules' 157 | ``` 158 | 159 | **[back to top](#thetop)** 160 | 161 | ## Related 162 | - [always-done](https://www.npmjs.com/package/always-done): Handle completion and errors with elegance! Support for streams, callbacks, promises, child… [more](https://github.com/hybridables/always-done#readme) | [homepage](https://github.com/hybridables/always-done#readme "Handle completion and errors with elegance! Support for streams, callbacks, promises, child processes, async/await and sync functions. A drop-in replacement for [async-done][] - pass 100% of its tests plus more") 163 | - [detect-installed](https://www.npmjs.com/package/detect-installed): Checks that given package is installed globally or locally. | [homepage](https://github.com/tunnckocore/detect-installed#readme "Checks that given package is installed globally or locally.") 164 | - [global-modules](https://www.npmjs.com/package/global-modules): The directory used by npm for globally installed npm modules. | [homepage](https://github.com/jonschlinkert/global-modules "The directory used by npm for globally installed npm modules.") 165 | - [global-paths](https://www.npmjs.com/package/global-paths): Returns an array of unique "global" directories based on the user's platform… [more](https://github.com/jonschlinkert/global-paths) | [homepage](https://github.com/jonschlinkert/global-paths "Returns an array of unique "global" directories based on the user's platform and environment. The resulting paths can be used for doing lookups for generators or other globally installed npm packages. Node.js / JavaScript.") 166 | - [global-prefix](https://www.npmjs.com/package/global-prefix): Get the npm global path prefix. | [homepage](https://github.com/jonschlinkert/global-prefix "Get the npm global path prefix.") 167 | - [is-installed](https://www.npmjs.com/package/is-installed): Checks that given package is installed locally or globally. Useful for robust… [more](https://github.com/tunnckocore/is-installed#readme) | [homepage](https://github.com/tunnckocore/is-installed#readme "Checks that given package is installed locally or globally. Useful for robust resolving when you want some package - it will check first if it exists locally, then if it exists globally") 168 | - [minibase](https://www.npmjs.com/package/minibase): Minimalist alternative for Base. Build complex APIs with small units called plugins… [more](https://github.com/node-minibase/minibase#readme) | [homepage](https://github.com/node-minibase/minibase#readme "Minimalist alternative for Base. Build complex APIs with small units called plugins. Works well with most of the already existing [base][] plugins.") 169 | - [try-catch-core](https://www.npmjs.com/package/try-catch-core): Low-level package to handle completion and errors of sync or asynchronous functions… [more](https://github.com/hybridables/try-catch-core#readme) | [homepage](https://github.com/hybridables/try-catch-core#readme "Low-level package to handle completion and errors of sync or asynchronous functions, using [once][] and [dezalgo][] libs. Useful for and used in higher-level libs such as [always-done][] to handle completion of anything.") 170 | 171 | **[back to top](#thetop)** 172 | 173 | ## Contributing 174 | Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue][open-issue-url]. 175 | Please read the [Contributing Guide](./CONTRIBUTING.md) and [Code of Conduct](./CODE_OF_CONDUCT.md) documents for advices. 176 | 177 | ## Author 178 | - [github/tunnckoCore](https://github.com/tunnckoCore) 179 | - [twitter/tunnckoCore](https://twitter.com/tunnckoCore) 180 | - [codementor/tunnckoCore](https://codementor.io/tunnckoCore) 181 | 182 | ## License 183 | Copyright © 2016-2017, [Charlike Mike Reagent](https://i.am.charlike.online). Released under the [MIT License](LICENSE). 184 | 185 | *** 186 | 187 | _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on October 12, 2017._ 188 | Project scaffolded and managed with [hela][]. 189 | 190 | [always-done]: https://github.com/hybridables/always-done 191 | [async-done]: https://github.com/gulpjs/async-done 192 | [base]: https://github.com/node-base/base 193 | [charlike-cli]: https://github.com/tunnckoCore/charlike-cli 194 | [dezalgo]: https://github.com/npm/dezalgo 195 | [global-modules]: https://github.com/jonschlinkert/global-modules 196 | [hela]: https://github.com/tunnckoCore/hela 197 | [once]: https://github.com/isaacs/once 198 | 199 | 200 | [npmv-url]: https://www.npmjs.com/package/get-installed-path 201 | [npmv-img]: https://img.shields.io/npm/v/get-installed-path.svg?label=npm%20version 202 | 203 | [open-issue-url]: https://github.com/tunnckoCoreLabs/get-installed-path/issues/new 204 | [github-release-url]: https://github.com/tunnckoCoreLabs/get-installed-path/releases/latest 205 | [github-release-img]: https://img.shields.io/github/release/tunnckoCoreLabs/get-installed-path.svg?label=github%20release 206 | 207 | [license-url]: https://github.com/tunnckoCoreLabs/get-installed-path/blob/master/LICENSE 208 | [license-img]: https://img.shields.io/npm/l/get-installed-path.svg 209 | 210 | [downloads-weekly-img]: https://img.shields.io/npm/dw/get-installed-path.svg 211 | [downloads-monthly-img]: https://img.shields.io/npm/dm/get-installed-path.svg 212 | [downloads-total-img]: https://img.shields.io/npm/dt/get-installed-path.svg 213 | 214 | 215 | [codeclimate-url]: https://codeclimate.com/github/tunnckoCoreLabs/get-installed-path 216 | [codeclimate-img]: https://img.shields.io/codeclimate/github/tunnckoCoreLabs/get-installed-path.svg 217 | 218 | [standard-url]: https://github.com/standard/standard 219 | [standard-img]: https://img.shields.io/badge/code_style-standard-brightgreen.svg 220 | 221 | [travis-url]: https://travis-ci.org/tunnckoCoreLabs/get-installed-path 222 | [travis-img]: https://img.shields.io/travis/tunnckoCoreLabs/get-installed-path/master.svg?label=linux 223 | 224 | [codecov-url]: https://codecov.io/gh/tunnckoCoreLabs/get-installed-path 225 | [codecov-img]: https://img.shields.io/codecov/c/github/tunnckoCoreLabs/get-installed-path/master.svg 226 | 227 | [dependencies-url]: https://david-dm.org/tunnckoCoreLabs/get-installed-path 228 | [dependencies-img]: https://img.shields.io/david/tunnckoCoreLabs/get-installed-path.svg 229 | 230 | [renovate-url]: https://renovateapp.com 231 | [renovate-img]: https://img.shields.io/badge/renovate-enabled-brightgreen.svg 232 | 233 | 234 | 235 | [chat-url]: https://tunnckocore.flock.com/?i=cx2xoeofjtj6eo6c 236 | [chat-img]: https://img.shields.io/badge/chat-on_flock-brightgreen.svg 237 | 238 | [prettier-url]: https://github.com/prettier/prettier 239 | [prettier-img]: https://img.shields.io/badge/styled_with-prettier-f952a5.svg 240 | 241 | [nodesecurity-url]: https://nodesecurity.io/orgs/tunnckocore/projects/976d071f-5f2e-4ca6-9583-8c2b9dbf6e76/master 242 | [nodesecurity-img]: https://nodesecurity.io/orgs/tunnckocore/projects/976d071f-5f2e-4ca6-9583-8c2b9dbf6e76/badge 243 | 245 | 246 | [semantic-release-url]: https://github.com/semantic-release/semantic-release 247 | [semantic-release-img]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg 248 | 249 | [ccommits-url]: https://conventionalcommits.org/ 250 | [ccommits-img]: https://img.shields.io/badge/conventional_commits-1.0.0-yellow.svg 251 | 252 | [nodeversion-url]: https://nodejs.org/en/download 253 | [nodeversion-img]: https://img.shields.io/node/v/get-installed-path.svg 254 | 255 | [first-timers-only-img]: https://img.shields.io/badge/first--timers--only-friendly-blue.svg 256 | [first-timers-only-url]: http://www.firsttimersonly.com 257 | 258 | [prs-welcome-img]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg 259 | [prs-welcome-url]: http://makeapullrequest.com 260 | 261 | [all-contributors-img]: https://img.shields.io/github/contributors/tunnckoCore/get-installed-path.svg?label=all%20contributors&colorB=ffa500 262 | 263 | [bithound-deps-url]: https://www.bithound.io/github/tunnckoCore/get-installed-path/master/dependencies/npm 264 | [bithound-deps-img]: https://www.bithound.io/github/tunnckoCore/get-installed-path/badges/dependencies.svg 265 | 266 | [bithound-code-url]: https://www.bithound.io/github/tunnckoCore/get-installed-path/master 267 | [bithound-code-img]: https://www.bithound.io/github/tunnckoCore/get-installed-path/badges/code.svg 268 | 269 | [paypal-donate-url]: https://paypal.me/tunnckoCore/10 270 | [paypal-donate-img]: https://img.shields.io/badge/paypal-donate-009cde.svg 271 | 272 | [tinyletter-url]: https://tinyletter.com/tunnckoCore 273 | [tinyletter-img]: https://img.shields.io/badge/newsletter-subscribe-9caaf8.svg 274 | 275 | [share-love-url]: https://twitter.com/intent/tweet?text=https://github.com/tunnckoCore/get-installed-path&via=tunnckoCore 276 | [share-love-img]: https://img.shields.io/badge/share-♥-ed1c24.svg 277 | 278 | --------------------------------------------------------------------------------