mirror of
https://github.com/hanzoai/cross-env.git
synced 2026-09-24 16:58:15 +00:00
fix: update all packages, tests, and README
This commit is contained in:
@@ -18,13 +18,10 @@ learn how: http://kcd.im/pull-request
|
|||||||
Relevant code or config
|
Relevant code or config
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
What you did:
|
What you did:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
What happened:
|
What happened:
|
||||||
|
|
||||||
<!-- Please provide the full error message/screenshots/anything -->
|
<!-- Please provide the full error message/screenshots/anything -->
|
||||||
@@ -38,6 +35,4 @@ minimal amount of code possible.
|
|||||||
|
|
||||||
Problem description:
|
Problem description:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Suggested solution:
|
Suggested solution:
|
||||||
|
|||||||
@@ -15,21 +15,27 @@ merge of your pull request!
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- What changes are being made? (What feature/bug is being fixed here?) -->
|
<!-- What changes are being made? (What feature/bug is being fixed here?) -->
|
||||||
|
|
||||||
**What**:
|
**What**:
|
||||||
|
|
||||||
<!-- Why are these changes necessary? -->
|
<!-- Why are these changes necessary? -->
|
||||||
|
|
||||||
**Why**:
|
**Why**:
|
||||||
|
|
||||||
<!-- How were these changes implemented? -->
|
<!-- How were these changes implemented? -->
|
||||||
|
|
||||||
**How**:
|
**How**:
|
||||||
|
|
||||||
<!-- Have you done all of these things? -->
|
<!-- Have you done all of these things? -->
|
||||||
|
|
||||||
**Checklist**:
|
**Checklist**:
|
||||||
|
|
||||||
<!-- add "N/A" to the end of each line that's irrelevant to your changes -->
|
<!-- add "N/A" to the end of each line that's irrelevant to your changes -->
|
||||||
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
|
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
|
||||||
|
|
||||||
- [ ] Documentation
|
- [ ] Documentation
|
||||||
- [ ] Tests
|
- [ ] Tests
|
||||||
- [ ] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
|
- [ ] Ready to be merged
|
||||||
- [ ] Added myself to contributors table <!-- this is optional, see the contributing guidelines for instructions -->
|
<!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->
|
||||||
|
|
||||||
<!-- feel free to add additional comments -->
|
<!-- feel free to add additional comments -->
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,5 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
The changelog is automatically updated using [semantic-release](https://github.com/semantic-release/semantic-release).
|
The changelog is automatically updated using
|
||||||
You can see it on the [releases page](../../releases).
|
[semantic-release](https://github.com/semantic-release/semantic-release). You
|
||||||
|
can see it on the [releases page](../../releases).
|
||||||
|
|||||||
+11
-44
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
Thanks for being willing to contribute!
|
Thanks for being willing to contribute!
|
||||||
|
|
||||||
**Working on your first Pull Request?** You can learn how from this *free* series
|
**Working on your first Pull Request?** You can learn how from this _free_
|
||||||
[How to Contribute to an Open Source Project on GitHub][egghead]
|
series [How to Contribute to an Open Source Project on GitHub][egghead]
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
|
|
||||||
1. Fork and clone the repo
|
1. Fork and clone the repo
|
||||||
2. `$ npm install` to install dependencies
|
2. `npm install` to install dependencies
|
||||||
3. `$ npm run validate` to validate you've got it working
|
3. `npm run validate` to validate you've got it working
|
||||||
4. Create a branch for your PR
|
4. Create a branch for your PR
|
||||||
|
|
||||||
> Tip: Keep your `master` branch pointing at the original repository and make
|
> Tip: Keep your `master` branch pointing at the original repository and make
|
||||||
@@ -21,45 +21,11 @@ Thanks for being willing to contribute!
|
|||||||
> git branch --set-upstream-to=upstream/master master
|
> git branch --set-upstream-to=upstream/master master
|
||||||
> ```
|
> ```
|
||||||
>
|
>
|
||||||
> This will add the original repository as a "remote" called "upstream,"
|
> This will add the original repository as a "remote" called "upstream," Then
|
||||||
> Then fetch the git information from that remote, then set your local `master`
|
> fetch the git information from that remote, then set your local `master`
|
||||||
> branch to use the upstream master branch whenever you run `git pull`.
|
> branch to use the upstream master branch whenever you run `git pull`. Then you
|
||||||
> Then you can make all of your pull request branches based on this `master`
|
> can make all of your pull request branches based on this `master` branch.
|
||||||
> branch. Whenever you want to update your version of `master`, do a regular
|
> Whenever you want to update your version of `master`, do a regular `git pull`.
|
||||||
> `git pull`.
|
|
||||||
|
|
||||||
## Add yourself as a contributor
|
|
||||||
|
|
||||||
This project follows the [all contributors][all-contributors] specification.
|
|
||||||
To add yourself to the table of contributors on the `README.md`, please use the
|
|
||||||
automated script as part of your PR:
|
|
||||||
|
|
||||||
```console
|
|
||||||
npm run add-contributor
|
|
||||||
```
|
|
||||||
|
|
||||||
Follow the prompt and commit `.all-contributorsrc` and `README.md` in the PR.
|
|
||||||
If you've already added yourself to the list and are making
|
|
||||||
a new type of contribution, you can run it again and select the added
|
|
||||||
contribution type.
|
|
||||||
|
|
||||||
## Committing and Pushing changes
|
|
||||||
|
|
||||||
Please make sure to run the tests before you commit your changes. You can run
|
|
||||||
`npm run test:update` which will update any snapshots that need updating.
|
|
||||||
Make sure to include those changes (if they exist) in your commit.
|
|
||||||
|
|
||||||
### opt into git hooks
|
|
||||||
|
|
||||||
There are git hooks set up with this project that are automatically installed
|
|
||||||
when you install dependencies. They're really handy, but are turned off by
|
|
||||||
default (so as to not hinder new contributors). You can opt into these by
|
|
||||||
creating a file called `.opt-in` at the root of the project and putting this
|
|
||||||
inside:
|
|
||||||
|
|
||||||
```
|
|
||||||
pre-commit
|
|
||||||
```
|
|
||||||
|
|
||||||
## Help needed
|
## Help needed
|
||||||
|
|
||||||
@@ -68,6 +34,7 @@ Please checkout the [the open issues][issues]
|
|||||||
Also, please watch the repo and respond to questions/bug reports/feature
|
Also, please watch the repo and respond to questions/bug reports/feature
|
||||||
requests! Thanks!
|
requests! Thanks!
|
||||||
|
|
||||||
[egghead]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github
|
[egghead]:
|
||||||
|
https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github
|
||||||
[all-contributors]: https://github.com/kentcdodds/all-contributors
|
[all-contributors]: https://github.com/kentcdodds/all-contributors
|
||||||
[issues]: https://github.com/kentcdodds/cross-env/issues
|
[issues]: https://github.com/kentcdodds/cross-env/issues
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
|
||||||
|
- [cross-env 🔀](#cross-env-)
|
||||||
|
- [The problem](#the-problem)
|
||||||
|
- [This solution](#this-solution)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Usage](#usage)
|
||||||
|
- [`cross-env` vs `cross-env-shell`](#cross-env-vs-cross-env-shell)
|
||||||
|
- [Windows Issues](#windows-issues)
|
||||||
|
- [Inspiration](#inspiration)
|
||||||
|
- [Other Solutions](#other-solutions)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [LICENSE](#license)
|
||||||
|
|
||||||
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://codefund.io/properties/445/visit-sponsor">
|
<a href="https://codefund.io/properties/445/visit-sponsor">
|
||||||
<img src="https://codefund.io/properties/445/sponsor" />
|
<img src="https://codefund.io/properties/445/sponsor" />
|
||||||
@@ -16,22 +33,11 @@ Run scripts that set and use environment variables across platforms
|
|||||||
[![Travis Build Status][build-badge]][build]
|
[![Travis Build Status][build-badge]][build]
|
||||||
[![AppVeyor Build Status][win-build-badge]][win-build]
|
[![AppVeyor Build Status][win-build-badge]][win-build]
|
||||||
[![Code Coverage][coverage-badge]][coverage]
|
[![Code Coverage][coverage-badge]][coverage]
|
||||||
[![Dependencies][dependencyci-badge]][dependencyci]
|
[![version][version-badge]][package] [![MIT License][license-badge]][license]
|
||||||
[![version][version-badge]][package]
|
|
||||||
[![node-version][node-version-badge]][node]
|
|
||||||
[![downloads][downloads-badge]][npm-stat]
|
|
||||||
|
|
||||||
[![MIT License][license-badge]][LICENSE]
|
|
||||||
[](#contributors)
|
[](#contributors)
|
||||||
[![PRs Welcome][prs-badge]][prs]
|
[![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc]
|
||||||
[![Donate][donate-badge]][donate]
|
[![downloads][downloads-badge]][npmtrends]
|
||||||
[![Code of Conduct][coc-badge]][coc]
|
|
||||||
[![Roadmap][roadmap-badge]][roadmap]
|
|
||||||
[![Examples][examples-badge]][examples]
|
|
||||||
|
|
||||||
[![Watch on GitHub][github-watch-badge]][github-watch]
|
|
||||||
[![Star on GitHub][github-star-badge]][github-star]
|
|
||||||
[![Tweet][twitter-badge]][twitter]
|
|
||||||
|
|
||||||
## The problem
|
## The problem
|
||||||
|
|
||||||
@@ -60,8 +66,8 @@ npm install --save-dev cross-env
|
|||||||
> WARNING! Make sure that when you're installing packages that you spell things
|
> WARNING! Make sure that when you're installing packages that you spell things
|
||||||
> correctly to avoid [mistakenly installing malware][malware]
|
> correctly to avoid [mistakenly installing malware][malware]
|
||||||
|
|
||||||
> NOTE : Version 6 of cross-env only supports Node.js 8 and higher, to use it on Node.js 7 or lower install version 5
|
> NOTE : Version 6 of cross-env only supports Node.js 8 and higher, to use it on
|
||||||
> ```npm install --save-dev cross-env@5 ```
|
> Node.js 7 or lower install version 5 `npm install --save-dev cross-env@5`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -100,12 +106,16 @@ Where `childScript` holds the actual command to execute and `parentScript` sets
|
|||||||
the environment variables to use. Then instead of run the childScript you run
|
the environment variables to use. Then instead of run the childScript you run
|
||||||
the parent. This is quite useful for launching the same command with different
|
the parent. This is quite useful for launching the same command with different
|
||||||
env variables or when the environment variables are too long to have everything
|
env variables or when the environment variables are too long to have everything
|
||||||
in one line. It also means that you can use `$GREET` env var syntax even on
|
in one line. It also means that you can use `$GREET` env var syntax even on
|
||||||
Windows which would usually require it to be `%GREET%`.
|
Windows which would usually require it to be `%GREET%`.
|
||||||
|
|
||||||
If you precede a dollar sign with an odd number of backslashes the expression statement will not be replaced. Note that this means backslashes after the JSON string escaping took place. `"FOO=\\$BAR"` will not be replaced. `"FOO=\\\\$BAR"` will be replaced though.
|
If you precede a dollar sign with an odd number of backslashes the expression
|
||||||
|
statement will not be replaced. Note that this means backslashes after the JSON
|
||||||
|
string escaping took place. `"FOO=\\$BAR"` will not be replaced.
|
||||||
|
`"FOO=\\\\$BAR"` will be replaced though.
|
||||||
|
|
||||||
Lastly, if you want to pass a JSON string (e.g., when using [ts-loader]), you can do as follows:
|
Lastly, if you want to pass a JSON string (e.g., when using [ts-loader]), you
|
||||||
|
can do as follows:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -115,21 +125,21 @@ Lastly, if you want to pass a JSON string (e.g., when using [ts-loader]), you ca
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Pay special attention to the **triple backslash** `(\\\)` **before** the **double quotes** `(")` and the **absence** of **single quotes** `(')`.
|
Pay special attention to the **triple backslash** `(\\\)` **before** the
|
||||||
Both of these conditions have to be met in order to work both on Windows and UNIX.
|
**double quotes** `(")` and the **absence** of **single quotes** `(')`. Both of
|
||||||
|
these conditions have to be met in order to work both on Windows and UNIX.
|
||||||
|
|
||||||
## `cross-env` vs `cross-env-shell`
|
## `cross-env` vs `cross-env-shell`
|
||||||
|
|
||||||
The `cross-env` module exposes two bins: `cross-env` and `cross-env-shell`. The
|
The `cross-env` module exposes two bins: `cross-env` and `cross-env-shell`. The
|
||||||
first one executes commands using [`cross-spawn`][cross-spawn], while the
|
first one executes commands using [`cross-spawn`][cross-spawn], while the second
|
||||||
second one uses the `shell` option from Node's `spawn`.
|
one uses the `shell` option from Node's `spawn`.
|
||||||
|
|
||||||
The main use case for `cross-env-shell` is when you need an environment
|
The main use case for `cross-env-shell` is when you need an environment variable
|
||||||
variable to be set across an entire inline shell script, rather than just one
|
to be set across an entire inline shell script, rather than just one command.
|
||||||
command.
|
|
||||||
|
|
||||||
For example, if you want to have the environment variable apply to several
|
For example, if you want to have the environment variable apply to several
|
||||||
commands in series then you will need to wrap those in quotes and use
|
commands in series then you will need to wrap those in quotes and use
|
||||||
`cross-env-shell` instead of `cross-env`.
|
`cross-env-shell` instead of `cross-env`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -140,29 +150,34 @@ commands in series then you will need to wrap those in quotes and use
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The rule of thumb is: if you want to pass to `cross-env` a command that
|
The rule of thumb is: if you want to pass to `cross-env` a command that contains
|
||||||
contains special shell characters *that you want interpreted*, then use
|
special shell characters _that you want interpreted_, then use
|
||||||
`cross-env-shell`. Otherwise stick to `cross-env`.
|
`cross-env-shell`. Otherwise stick to `cross-env`.
|
||||||
|
|
||||||
On Windows you need to use `cross-env-shell`, if you want to handle [signal events](https://nodejs.org/api/process.html#process_signal_events) inside of your program. A common case for that is when you want to capture a `SIGINT` event invoked by pressing `Ctrl + C` on the command-line interface.
|
On Windows you need to use `cross-env-shell`, if you want to handle
|
||||||
|
[signal events](https://nodejs.org/api/process.html#process_signal_events)
|
||||||
|
inside of your program. A common case for that is when you want to capture a
|
||||||
|
`SIGINT` event invoked by pressing `Ctrl + C` on the command-line interface.
|
||||||
|
|
||||||
## Windows Issues
|
## Windows Issues
|
||||||
|
|
||||||
Please note that `npm` uses `cmd` by default and that doesn't support command
|
Please note that `npm` uses `cmd` by default and that doesn't support command
|
||||||
substitution, so if you want to leaverage that, then you need to update your
|
substitution, so if you want to leverage that, then you need to update your
|
||||||
`.npmrc` to set the `script-shell` to powershell.
|
`.npmrc` to set the `script-shell` to powershell.
|
||||||
[Learn more here](https://github.com/kentcdodds/cross-env/issues/192#issuecomment-513341729).
|
[Learn more here](https://github.com/kentcdodds/cross-env/issues/192#issuecomment-513341729).
|
||||||
|
|
||||||
## Inspiration
|
## Inspiration
|
||||||
|
|
||||||
I originally created this to solve a problem I was having with my npm scripts in
|
I originally created this to solve a problem I was having with my npm scripts in
|
||||||
[angular-formly][angular-formly]. This made contributing to the project
|
[angular-formly][angular-formly]. This made contributing to the project much
|
||||||
much easier for Windows users.
|
easier for Windows users.
|
||||||
|
|
||||||
## Other Solutions
|
## Other Solutions
|
||||||
|
|
||||||
- [`env-cmd`](https://github.com/toddbluhm/env-cmd) - Reads environment variables from a file instead
|
- [`env-cmd`](https://github.com/toddbluhm/env-cmd) - Reads environment
|
||||||
- [`@naholyr/cross-env`](https://www.npmjs.com/package/@naholyr/cross-env) - `cross-env` with support for setting default values
|
variables from a file instead
|
||||||
|
- [`@naholyr/cross-env`](https://www.npmjs.com/package/@naholyr/cross-env) -
|
||||||
|
`cross-env` with support for setting default values
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
@@ -201,11 +216,12 @@ Thanks goes to these people ([emoji key][emojis]):
|
|||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
This project follows the [all-contributors][all-contributors] specification. Contributions of any kind welcome!
|
This project follows the [all-contributors][all-contributors] specification.
|
||||||
|
Contributions of any kind welcome!
|
||||||
|
|
||||||
> Note: this was added late into the project. If you've contributed to this
|
> Note: this was added late into the project. If you've contributed to this
|
||||||
> project in any way, please make a pull request to add yourself to the list
|
> project in any way, please make a pull request to add yourself to the list by
|
||||||
> by following the instructions in the `CONTRIBUTING.md`
|
> following the instructions in the `CONTRIBUTING.md`
|
||||||
|
|
||||||
## LICENSE
|
## LICENSE
|
||||||
|
|
||||||
@@ -213,41 +229,33 @@ MIT
|
|||||||
|
|
||||||
[npm]: https://www.npmjs.com/
|
[npm]: https://www.npmjs.com/
|
||||||
[node]: https://nodejs.org
|
[node]: https://nodejs.org
|
||||||
[build-badge]: https://img.shields.io/travis/kentcdodds/cross-env.svg?style=flat-square
|
[build-badge]:
|
||||||
|
https://img.shields.io/travis/kentcdodds/cross-env.svg?style=flat-square
|
||||||
[build]: https://travis-ci.org/kentcdodds/cross-env
|
[build]: https://travis-ci.org/kentcdodds/cross-env
|
||||||
[win-build-badge]: https://img.shields.io/appveyor/ci/kentcdodds/cross-env.svg?style=flat-square
|
[win-build-badge]:
|
||||||
|
https://img.shields.io/appveyor/ci/kentcdodds/cross-env.svg?style=flat-square
|
||||||
[win-build]: https://ci.appveyor.com/project/kentcdodds/cross-env
|
[win-build]: https://ci.appveyor.com/project/kentcdodds/cross-env
|
||||||
[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/cross-env.svg?style=flat-square
|
[coverage-badge]:
|
||||||
|
https://img.shields.io/codecov/c/github/kentcdodds/cross-env.svg?style=flat-square
|
||||||
[coverage]: https://codecov.io/github/kentcdodds/cross-env
|
[coverage]: https://codecov.io/github/kentcdodds/cross-env
|
||||||
[dependencyci-badge]: https://dependencyci.com/github/kentcdodds/cross-env/badge?style=flat-square
|
|
||||||
[dependencyci]: https://dependencyci.com/github/kentcdodds/cross-env
|
|
||||||
[version-badge]: https://img.shields.io/npm/v/cross-env.svg?style=flat-square
|
[version-badge]: https://img.shields.io/npm/v/cross-env.svg?style=flat-square
|
||||||
[package]: https://www.npmjs.com/package/cross-env
|
[package]: https://www.npmjs.com/package/cross-env
|
||||||
[node-version-badge]: https://img.shields.io/badge/node-%3E%3D%204.0-orange.svg?style=flat-square
|
|
||||||
[downloads-badge]: https://img.shields.io/npm/dm/cross-env.svg?style=flat-square
|
[downloads-badge]: https://img.shields.io/npm/dm/cross-env.svg?style=flat-square
|
||||||
[npm-stat]: http://npm-stat.com/charts.html?package=cross-env&from=2016-04-01
|
[npmtrends]: https://www.npmtrends.com/cross-env
|
||||||
[license-badge]: https://img.shields.io/npm/l/cross-env.svg?style=flat-square
|
[license-badge]: https://img.shields.io/npm/l/cross-env.svg?style=flat-square
|
||||||
[license]: https://github.com/kentcdodds/cross-env/blob/master/other/LICENSE
|
[license]: https://github.com/kentcdodds/cross-env/blob/master/other/LICENSE
|
||||||
[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
[prs-badge]:
|
||||||
|
https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
|
||||||
[prs]: http://makeapullrequest.com
|
[prs]: http://makeapullrequest.com
|
||||||
[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square
|
[coc-badge]:
|
||||||
[donate]: http://kcd.im/donate
|
https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
|
||||||
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
|
[coc]:
|
||||||
[coc]: https://github.com/kentcdodds/cross-env/blob/master/other/CODE_OF_CONDUCT.md
|
https://github.com/kentcdodds/cross-env/blob/master/other/CODE_OF_CONDUCT.md
|
||||||
[roadmap-badge]: https://img.shields.io/badge/%F0%9F%93%94-roadmap-CD9523.svg?style=flat-square
|
|
||||||
[roadmap]: https://github.com/kentcdodds/cross-env/blob/master/other/ROADMAP.md
|
|
||||||
[examples-badge]: https://img.shields.io/badge/%F0%9F%92%A1-examples-8C8E93.svg?style=flat-square
|
|
||||||
[examples]: https://github.com/kentcdodds/cross-env/blob/master/other/EXAMPLES.md
|
|
||||||
[github-watch-badge]: https://img.shields.io/github/watchers/kentcdodds/cross-env.svg?style=social
|
|
||||||
[github-watch]: https://github.com/kentcdodds/cross-env/watchers
|
|
||||||
[github-star-badge]: https://img.shields.io/github/stars/kentcdodds/cross-env.svg?style=social
|
|
||||||
[github-star]: https://github.com/kentcdodds/cross-env/stargazers
|
|
||||||
[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20cross-env!%20https://github.com/kentcdodds/cross-env%20%F0%9F%91%8D
|
|
||||||
[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/kentcdodds/cross-env.svg?style=social
|
|
||||||
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
|
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
|
||||||
[all-contributors]: https://github.com/kentcdodds/all-contributors
|
[all-contributors]: https://github.com/kentcdodds/all-contributors
|
||||||
[win-bash]: https://msdn.microsoft.com/en-us/commandline/wsl/about
|
[win-bash]: https://msdn.microsoft.com/en-us/commandline/wsl/about
|
||||||
[angular-formly]: https://github.com/formly-js/angular-formly
|
[angular-formly]: https://github.com/formly-js/angular-formly
|
||||||
[cross-spawn]: https://www.npmjs.com/package/cross-spawn
|
[cross-spawn]: https://www.npmjs.com/package/cross-spawn
|
||||||
[ts-loader]: https://www.npmjs.com/package/ts-loader
|
[ts-loader]: https://www.npmjs.com/package/ts-loader
|
||||||
[malware]: http://blog.npmjs.org/post/163723642530/crossenv-malware-on-the-npm-registry
|
[malware]:
|
||||||
|
http://blog.npmjs.org/post/163723642530/crossenv-malware-on-the-npm-registry
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
const __mock = {
|
|
||||||
reset() {
|
|
||||||
__mock.spawned = null
|
|
||||||
Object.assign(module.exports, {
|
|
||||||
__mock,
|
|
||||||
spawn: jest.fn(() => {
|
|
||||||
__mock.spawned = {
|
|
||||||
on: jest.fn(),
|
|
||||||
kill: jest.fn(),
|
|
||||||
}
|
|
||||||
return __mock.spawned
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
__mock.reset()
|
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
const jestConfig = require('kcd-scripts/config').jest
|
const jestConfig = require('kcd-scripts/config').jest
|
||||||
|
|
||||||
jestConfig.coveragePathIgnorePatterns = jestConfig.coveragePathIgnorePatterns.concat(
|
jestConfig.coveragePathIgnorePatterns = jestConfig.coveragePathIgnorePatterns.concat(
|
||||||
['/bin/']
|
['/bin/'],
|
||||||
)
|
)
|
||||||
module.exports = jestConfig
|
module.exports = jestConfig
|
||||||
|
|||||||
+24
-23
@@ -5,30 +5,30 @@
|
|||||||
In the interest of fostering an open and welcoming environment, we as
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
contributors and maintainers pledge to making participation in our project and
|
contributors and maintainers pledge to making participation in our project and
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
size, disability, ethnicity, gender identity and expression, level of
|
||||||
nationality, personal appearance, race, religion, or sexual identity and
|
experience, nationality, personal appearance, race, religion, or sexual identity
|
||||||
orientation.
|
and orientation.
|
||||||
|
|
||||||
## Our Standards
|
## Our Standards
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment
|
Examples of behavior that contributes to creating a positive environment
|
||||||
include:
|
include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances
|
advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic
|
- Publishing others' private information, such as a physical or electronic
|
||||||
address, without explicit permission
|
address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
@@ -37,11 +37,11 @@ Project maintainers are responsible for clarifying the standards of acceptable
|
|||||||
behavior and are expected to take appropriate and fair corrective action in
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
response to any instances of unacceptable behavior.
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or
|
Project maintainers have the right and responsibility to remove, edit, or reject
|
||||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
not aligned to this Code of Conduct, or to ban temporarily or permanently any
|
||||||
permanently any contributor for other behaviors that they deem inappropriate,
|
contributor for other behaviors that they deem inappropriate, threatening,
|
||||||
threatening, offensive, or harmful.
|
offensive, or harmful.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
@@ -58,8 +58,9 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|||||||
reported by contacting the project team at kent+coc@doddsfamily.us. All
|
reported by contacting the project team at kent+coc@doddsfamily.us. All
|
||||||
complaints will be reviewed and investigated and will result in a response that
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
is deemed necessary and appropriate to the circumstances. The project team is
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
obligated to maintain confidentiality with regard to the reporter of an
|
||||||
Further details of specific enforcement policies may be posted separately.
|
incident. Further details of specific enforcement policies may be posted
|
||||||
|
separately.
|
||||||
|
|
||||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
faith may face temporary or permanent repercussions as determined by other
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
@@ -67,8 +68,8 @@ members of the project's leadership.
|
|||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
available at [http://contributor-covenant.org/version/1/4][version]
|
version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
[homepage]: http://contributor-covenant.org
|
[homepage]: http://contributor-covenant.org
|
||||||
[version]: http://contributor-covenant.org/version/1/4/
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
|
|||||||
+22
-10
@@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cross-env",
|
"name": "cross-env",
|
||||||
"version": "0.0.0-semantically-released",
|
"version": "0.0.0-semantically-released",
|
||||||
"description":
|
"description": "Run scripts that set and use environment variables across platforms",
|
||||||
"Run scripts that set and use environment variables across platforms",
|
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"cross-env": "dist/bin/cross-env.js",
|
"cross-env": "dist/bin/cross-env.js",
|
||||||
@@ -12,28 +11,41 @@
|
|||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"add-contributor": "kcd-scripts contributors add",
|
|
||||||
"build": "kcd-scripts build",
|
"build": "kcd-scripts build",
|
||||||
"lint": "kcd-scripts lint",
|
"lint": "kcd-scripts lint",
|
||||||
"test": "kcd-scripts test",
|
"test": "kcd-scripts test",
|
||||||
"test:update": "npm test -- --updateSnapshot --coverage",
|
"validate": "kcd-scripts validate"
|
||||||
"validate": "kcd-scripts validate",
|
|
||||||
"precommit": "kcd-scripts precommit"
|
|
||||||
},
|
},
|
||||||
"files": ["dist"],
|
"husky": {
|
||||||
"keywords": ["cross-environment", "environment variable", "windows"],
|
"hooks": {
|
||||||
|
"pre-commit": "kcd-scripts pre-commit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"cross-environment",
|
||||||
|
"environment variable",
|
||||||
|
"windows"
|
||||||
|
],
|
||||||
"author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)",
|
"author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.6.2",
|
||||||
"cross-spawn": "^7.0.0"
|
"cross-spawn": "^7.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"kcd-scripts": "^0.3.4"
|
"kcd-scripts": "^1.8.0"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "./node_modules/kcd-scripts/eslint.js"
|
"extends": "./node_modules/kcd-scripts/eslint.js"
|
||||||
},
|
},
|
||||||
"eslintIgnore": ["node_modules", "coverage", "dist"],
|
"eslintIgnore": [
|
||||||
|
"node_modules",
|
||||||
|
"coverage",
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/kentcdodds/cross-env.git"
|
"url": "https://github.com/kentcdodds/cross-env.git"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require('kcd-scripts/prettier')
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
const __mock = {
|
|
||||||
reset() {
|
|
||||||
Object.assign(__mock, {returnValue: false})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
__mock.reset()
|
|
||||||
|
|
||||||
module.exports = function isWindowsMock() {
|
|
||||||
return __mock.returnValue
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.assign(module.exports, {__mock})
|
|
||||||
+20
-15
@@ -8,15 +8,16 @@ const env = {
|
|||||||
test1: 'b',
|
test1: 'b',
|
||||||
test2: 'c',
|
test2: 'c',
|
||||||
test3: 'd',
|
test3: 'd',
|
||||||
'empty_var': ''
|
// eslint-disable-next-line babel/camelcase
|
||||||
|
empty_var: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
afterEach(() => {
|
||||||
isWindowsMock.__mock.reset()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts unix-style env variable usage for windows`, () => {
|
test(`converts unix-style env variable usage for windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(commandConvert('$test', env)).toBe('%test%')
|
expect(commandConvert('$test', env)).toBe('%test%')
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -25,51 +26,55 @@ test(`leaves command unchanged when not a variable`, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert windows-style env variable`, () => {
|
test(`doesn't convert windows-style env variable`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(commandConvert('%test%', env)).toBe('%test%')
|
expect(commandConvert('%test%', env)).toBe('%test%')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`leaves variable unchanged when using correct operating system`, () => {
|
test(`leaves variable unchanged when using correct operating system`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(commandConvert('$test', env)).toBe('$test')
|
expect(commandConvert('$test', env)).toBe('$test')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`is stateless`, () => {
|
test(`is stateless`, () => {
|
||||||
// this test prevents falling into regexp traps like this:
|
// this test prevents falling into regexp traps like this:
|
||||||
// http://stackoverflow.com/a/1520853/971592
|
// http://stackoverflow.com/a/1520853/971592
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(commandConvert('$test', env)).toBe(commandConvert('$test', env))
|
expect(commandConvert('$test', env)).toBe(commandConvert('$test', env))
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts embedded unix-style env variables usage for windows`, () => {
|
test(`converts embedded unix-style env variables usage for windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(commandConvert('$test1/$test2/$test3', env)).toBe('%test1%/%test2%/%test3%')
|
expect(commandConvert('$test1/$test2/$test3', env)).toBe(
|
||||||
|
'%test1%/%test2%/%test3%',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
test(`leaves embedded variables unchanged when using correct operating system`, () => {
|
test(`leaves embedded variables unchanged when using correct operating system`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(commandConvert('$test1/$test2/$test3', env)).toBe('$test1/$test2/$test3')
|
expect(commandConvert('$test1/$test2/$test3', env)).toBe(
|
||||||
|
'$test1/$test2/$test3',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts braced unix-style env variable usage for windows`, () => {
|
test(`converts braced unix-style env variable usage for windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
expect(commandConvert('${test}', env)).toBe('%test%')
|
expect(commandConvert('${test}', env)).toBe('%test%')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`removes non-existent variables from the converted command`, () => {
|
test(`removes non-existent variables from the converted command`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(commandConvert('$test1/$foo/$test2', env)).toBe('%test1%//%test2%')
|
expect(commandConvert('$test1/$foo/$test2', env)).toBe('%test1%//%test2%')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`removes empty variables from the converted command`, () => {
|
test(`removes empty variables from the converted command`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(commandConvert('$foo/$test/$empty_var', env)).toBe('/%test%/')
|
expect(commandConvert('$foo/$test/$empty_var', env)).toBe('/%test%/')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`normalizes command on windows`, () => {
|
test(`normalizes command on windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
// index.js calls `commandConvert` with `normalize` param
|
// index.js calls `commandConvert` with `normalize` param
|
||||||
// as `true` for command only
|
// as `true` for command only
|
||||||
expect(commandConvert('./cmd.bat', env, true)).toBe('cmd.bat')
|
expect(commandConvert('./cmd.bat', env, true)).toBe('cmd.bat')
|
||||||
|
|||||||
+71
-74
@@ -2,24 +2,33 @@ import crossSpawnMock from 'cross-spawn'
|
|||||||
import isWindowsMock from '../is-windows'
|
import isWindowsMock from '../is-windows'
|
||||||
|
|
||||||
jest.mock('../is-windows')
|
jest.mock('../is-windows')
|
||||||
|
jest.mock('cross-spawn')
|
||||||
|
|
||||||
const crossEnv = require('../')
|
const crossEnv = require('../')
|
||||||
|
|
||||||
|
const getSpawned = (call = 0) => crossSpawnMock.spawn.mock.results[call].value
|
||||||
|
|
||||||
process.setMaxListeners(20)
|
process.setMaxListeners(20)
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
crossSpawnMock.__mock.reset()
|
jest.spyOn(process, 'exit').mockImplementation(() => {})
|
||||||
|
crossSpawnMock.spawn.mockReturnValue({on: jest.fn(), kill: jest.fn()})
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should set environment variables and run the remaining command`, () => {
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
process.exit.mockRestore()
|
||||||
|
})
|
||||||
|
|
||||||
|
test(`sets environment variables and run the remaining command`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'production'}, 'FOO_ENV=production')
|
testEnvSetting({FOO_ENV: 'production'}, 'FOO_ENV=production')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should APPDATA be undefined and not string`, () => {
|
test(`APPDATA is undefined and not string`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'production', APPDATA: 2}, 'FOO_ENV=production')
|
testEnvSetting({FOO_ENV: 'production', APPDATA: 2}, 'FOO_ENV=production')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle multiple env variables`, () => {
|
test(`handles multiple env variables`, () => {
|
||||||
testEnvSetting(
|
testEnvSetting(
|
||||||
{
|
{
|
||||||
FOO_ENV: 'production',
|
FOO_ENV: 'production',
|
||||||
@@ -32,35 +41,35 @@ it(`should handle multiple env variables`, () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle special characters`, () => {
|
test(`handles special characters`, () => {
|
||||||
testEnvSetting({FOO_ENV: './!?'}, 'FOO_ENV=./!?')
|
testEnvSetting({FOO_ENV: './!?'}, 'FOO_ENV=./!?')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle single-quoted strings`, () => {
|
test(`handles single-quoted strings`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'bar env'}, "FOO_ENV='bar env'")
|
testEnvSetting({FOO_ENV: 'bar env'}, "FOO_ENV='bar env'")
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle double-quoted strings`, () => {
|
test(`handles double-quoted strings`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'bar env'}, 'FOO_ENV="bar env"')
|
testEnvSetting({FOO_ENV: 'bar env'}, 'FOO_ENV="bar env"')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle equality signs in quoted strings`, () => {
|
test(`handles equality signs in quoted strings`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle empty single-quoted strings`, () => {
|
test(`handles empty single-quoted strings`, () => {
|
||||||
testEnvSetting({FOO_ENV: ''}, "FOO_ENV=''")
|
testEnvSetting({FOO_ENV: ''}, "FOO_ENV=''")
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle empty double-quoted strings`, () => {
|
test(`handles empty double-quoted strings`, () => {
|
||||||
testEnvSetting({FOO_ENV: ''}, 'FOO_ENV=""')
|
testEnvSetting({FOO_ENV: ''}, 'FOO_ENV=""')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle no value after the equals sign`, () => {
|
test(`handles no value after the equals sign`, () => {
|
||||||
testEnvSetting({FOO_ENV: ''}, 'FOO_ENV=')
|
testEnvSetting({FOO_ENV: ''}, 'FOO_ENV=')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle quoted scripts`, () => {
|
test(`handles quoted scripts`, () => {
|
||||||
crossEnv(['GREETING=Hi', 'NAME=Joe', 'echo $GREETING && echo $NAME'], {
|
crossEnv(['GREETING=Hi', 'NAME=Joe', 'echo $GREETING && echo $NAME'], {
|
||||||
shell: true,
|
shell: true,
|
||||||
})
|
})
|
||||||
@@ -70,15 +79,12 @@ it(`should handle quoted scripts`, () => {
|
|||||||
{
|
{
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
shell: true,
|
shell: true,
|
||||||
env: Object.assign({}, process.env, {
|
env: {...process.env, GREETING: 'Hi', NAME: 'Joe'},
|
||||||
GREETING: 'Hi',
|
|
||||||
NAME: 'Joe',
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should handle escaped characters`, () => {
|
test(`handles escaped characters`, () => {
|
||||||
// this escapes \,",' and $
|
// this escapes \,",' and $
|
||||||
crossEnv(
|
crossEnv(
|
||||||
['GREETING=Hi', 'NAME=Joe', 'echo \\"\\\'\\$GREETING\\\'\\" && echo $NAME'],
|
['GREETING=Hi', 'NAME=Joe', 'echo \\"\\\'\\$GREETING\\\'\\" && echo $NAME'],
|
||||||
@@ -92,96 +98,88 @@ it(`should handle escaped characters`, () => {
|
|||||||
{
|
{
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
shell: true,
|
shell: true,
|
||||||
env: Object.assign({}, process.env, {
|
env: {...process.env, GREETING: 'Hi', NAME: 'Joe'},
|
||||||
GREETING: 'Hi',
|
|
||||||
NAME: 'Joe',
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should do nothing given no command`, () => {
|
test(`does nothing when given no command`, () => {
|
||||||
crossEnv([])
|
crossEnv([])
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledTimes(0)
|
expect(crossSpawnMock.spawn).toHaveBeenCalledTimes(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should normalize command on windows`, () => {
|
test(`normalizes commands on windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
crossEnv(['./cmd.bat'])
|
crossEnv(['./cmd.bat'])
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledWith('cmd.bat', [], {
|
expect(crossSpawnMock.spawn).toHaveBeenCalledWith('cmd.bat', [], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: Object.assign({}, process.env),
|
env: {...process.env},
|
||||||
})
|
})
|
||||||
isWindowsMock.__mock.reset()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should not normalize command arguments on windows`, () => {
|
test(`does not normalize command arguments on windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
crossEnv(['echo', 'http://example.com'])
|
crossEnv(['echo', 'http://example.com'])
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledWith(
|
expect(crossSpawnMock.spawn).toHaveBeenCalledWith(
|
||||||
'echo',
|
'echo',
|
||||||
['http://example.com'],
|
['http://example.com'],
|
||||||
{
|
{
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: Object.assign({}, process.env),
|
env: {...process.env},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
isWindowsMock.__mock.reset()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should propagate kill signals`, () => {
|
test(`propagates kill signals`, () => {
|
||||||
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
||||||
|
|
||||||
process.emit('SIGTERM')
|
process.emit('SIGTERM')
|
||||||
process.emit('SIGINT')
|
process.emit('SIGINT')
|
||||||
process.emit('SIGHUP')
|
process.emit('SIGHUP')
|
||||||
process.emit('SIGBREAK')
|
process.emit('SIGBREAK')
|
||||||
expect(crossSpawnMock.__mock.spawned.kill).toHaveBeenCalledWith('SIGTERM')
|
const spawned = getSpawned()
|
||||||
expect(crossSpawnMock.__mock.spawned.kill).toHaveBeenCalledWith('SIGINT')
|
expect(spawned.kill).toHaveBeenCalledWith('SIGTERM')
|
||||||
expect(crossSpawnMock.__mock.spawned.kill).toHaveBeenCalledWith('SIGHUP')
|
expect(spawned.kill).toHaveBeenCalledWith('SIGINT')
|
||||||
expect(crossSpawnMock.__mock.spawned.kill).toHaveBeenCalledWith('SIGBREAK')
|
expect(spawned.kill).toHaveBeenCalledWith('SIGHUP')
|
||||||
|
expect(spawned.kill).toHaveBeenCalledWith('SIGBREAK')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should propagate unhandled exit signal`, () => {
|
test(`keeps backslashes`, () => {
|
||||||
process.exit = jest.fn()
|
isWindowsMock.mockReturnValue(true)
|
||||||
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
|
||||||
const spawnExitCallback = crossSpawnMock.__mock.spawned.on.mock.calls[0][1]
|
|
||||||
const spawnExitCode = null
|
|
||||||
spawnExitCallback(spawnExitCode)
|
|
||||||
expect(process.exit).toHaveBeenCalledWith(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
it(`should exit cleanly with SIGINT with a null exit code`, () => {
|
|
||||||
process.exit = jest.fn()
|
|
||||||
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
|
||||||
const spawnExitCallback = crossSpawnMock.__mock.spawned.on.mock.calls[0][1]
|
|
||||||
const spawnExitCode = null
|
|
||||||
const spawnExitSignal = 'SIGINT'
|
|
||||||
spawnExitCallback(spawnExitCode, spawnExitSignal)
|
|
||||||
expect(process.exit).toHaveBeenCalledWith(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it(`should propagate regular exit code`, () => {
|
|
||||||
process.exit = jest.fn()
|
|
||||||
testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
|
||||||
const spawnExitCallback = crossSpawnMock.__mock.spawned.on.mock.calls[0][1]
|
|
||||||
const spawnExitCode = 0
|
|
||||||
spawnExitCallback(spawnExitCode)
|
|
||||||
expect(process.exit).toHaveBeenCalledWith(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it(`should keep backslashes`, () => {
|
|
||||||
isWindowsMock.__mock.returnValue = true
|
|
||||||
crossEnv(['echo', '\\\\\\\\someshare\\\\somefolder'])
|
crossEnv(['echo', '\\\\\\\\someshare\\\\somefolder'])
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledWith(
|
expect(crossSpawnMock.spawn).toHaveBeenCalledWith(
|
||||||
'echo',
|
'echo',
|
||||||
['\\\\someshare\\somefolder'],
|
['\\\\someshare\\somefolder'],
|
||||||
{
|
{
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: Object.assign({}, process.env),
|
env: {...process.env},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
isWindowsMock.__mock.reset()
|
})
|
||||||
|
|
||||||
|
test(`propagates unhandled exit signal`, () => {
|
||||||
|
const {spawned} = testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
||||||
|
const spawnExitCallback = spawned.on.mock.calls[0][1]
|
||||||
|
const spawnExitCode = null
|
||||||
|
spawnExitCallback(spawnExitCode)
|
||||||
|
expect(process.exit).toHaveBeenCalledWith(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test(`exits cleanly with SIGINT with a null exit code`, () => {
|
||||||
|
const {spawned} = testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
||||||
|
const spawnExitCallback = spawned.on.mock.calls[0][1]
|
||||||
|
const spawnExitCode = null
|
||||||
|
const spawnExitSignal = 'SIGINT'
|
||||||
|
spawnExitCallback(spawnExitCode, spawnExitSignal)
|
||||||
|
expect(process.exit).toHaveBeenCalledWith(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test(`propagates regular exit code`, () => {
|
||||||
|
const {spawned} = testEnvSetting({FOO_ENV: 'foo=bar'}, 'FOO_ENV="foo=bar"')
|
||||||
|
const spawnExitCallback = spawned.on.mock.calls[0][1]
|
||||||
|
const spawnExitCode = 0
|
||||||
|
spawnExitCallback(spawnExitCode)
|
||||||
|
expect(process.exit).toHaveBeenCalledWith(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
function testEnvSetting(expected, ...envSettings) {
|
function testEnvSetting(expected, ...envSettings) {
|
||||||
@@ -200,17 +198,16 @@ function testEnvSetting(expected, ...envSettings) {
|
|||||||
env.APPDATA = process.env.APPDATA
|
env.APPDATA = process.env.APPDATA
|
||||||
}
|
}
|
||||||
Object.assign(env, expected)
|
Object.assign(env, expected)
|
||||||
expect(ret).toBe(crossSpawnMock.__mock.spawned)
|
const spawned = getSpawned()
|
||||||
|
expect(ret).toBe(spawned)
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledTimes(1)
|
expect(crossSpawnMock.spawn).toHaveBeenCalledTimes(1)
|
||||||
expect(crossSpawnMock.spawn).toHaveBeenCalledWith('echo', ['hello world'], {
|
expect(crossSpawnMock.spawn).toHaveBeenCalledWith('echo', ['hello world'], {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
shell: undefined,
|
shell: undefined,
|
||||||
env: Object.assign({}, process.env, env),
|
env: {...process.env, ...env},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(crossSpawnMock.__mock.spawned.on).toHaveBeenCalledTimes(1)
|
expect(spawned.on).toHaveBeenCalledTimes(1)
|
||||||
expect(crossSpawnMock.__mock.spawned.on).toHaveBeenCalledWith(
|
expect(spawned.on).toHaveBeenCalledWith('exit', expect.any(Function))
|
||||||
'exit',
|
return {spawned}
|
||||||
expect.any(Function),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,32 @@
|
|||||||
import isWindows from "../is-windows"
|
import isWindows from '../is-windows'
|
||||||
|
|
||||||
it(`should return true if the current OS is Windows`, () => {
|
const {
|
||||||
process.platform = 'win32'
|
platform,
|
||||||
expect(isWindows()).toBe(true)
|
env: {OSTYPE},
|
||||||
|
} = process
|
||||||
|
|
||||||
|
// make the platform property writeable
|
||||||
|
Object.defineProperty(process, 'platform', {
|
||||||
|
value: platform,
|
||||||
|
writable: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should return false if the current OS is not Windows`, () => {
|
afterEach(() => {
|
||||||
|
process.platform = platform
|
||||||
|
process.env.OSTYPE = OSTYPE
|
||||||
|
})
|
||||||
|
|
||||||
|
test(`returns true if the current OS is Windows`, () => {
|
||||||
|
process.platform = 'win32'
|
||||||
|
expect(isWindows()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test(`returns false if the current OS is not Windows`, () => {
|
||||||
process.platform = 'linux'
|
process.platform = 'linux'
|
||||||
expect(isWindows()).toBe(false)
|
expect(isWindows()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should return true if the OSTYPE is cygwin or msys`, () => {
|
test(`returns true if the OSTYPE is cygwin or msys`, () => {
|
||||||
process.platform = 'linux'
|
process.platform = 'linux'
|
||||||
|
|
||||||
process.env.OSTYPE = 'cygwin'
|
process.env.OSTYPE = 'cygwin'
|
||||||
@@ -22,4 +37,4 @@ it(`should return true if the OSTYPE is cygwin or msys`, () => {
|
|||||||
|
|
||||||
process.env.OSTYPE = ''
|
process.env.OSTYPE = ''
|
||||||
expect(isWindows()).toBe(false)
|
expect(isWindows()).toBe(false)
|
||||||
})
|
})
|
||||||
|
|||||||
+21
-21
@@ -9,7 +9,6 @@ beforeEach(() => {
|
|||||||
process.env.VAR1 = 'value1'
|
process.env.VAR1 = 'value1'
|
||||||
process.env.VAR2 = 'value2'
|
process.env.VAR2 = 'value2'
|
||||||
process.env.JSON_VAR = JSON_VALUE
|
process.env.JSON_VAR = JSON_VALUE
|
||||||
isWindowsMock.__mock.reset()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -17,105 +16,106 @@ afterEach(() => {
|
|||||||
delete env.VAR1
|
delete env.VAR1
|
||||||
delete env.VAR2
|
delete env.VAR2
|
||||||
delete env.JSON_VAR
|
delete env.JSON_VAR
|
||||||
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't affect simple variable values`, () => {
|
test(`doesn't affect simple variable values`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo')).toBe('foo')
|
expect(varValueConvert('foo')).toBe('foo')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert a ; into a : on UNIX`, () => {
|
test(`doesn't convert a ; into a : on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('foo;bar', 'PATH')).toBe('foo;bar')
|
expect(varValueConvert('foo;bar', 'PATH')).toBe('foo;bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert a ; into a : for non-PATH on UNIX`, () => {
|
test(`doesn't convert a ; into a : for non-PATH on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('foo;bar', 'FOO')).toBe('foo;bar')
|
expect(varValueConvert('foo;bar', 'FOO')).toBe('foo;bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert a ; into a : for non-PATH on Windows`, () => {
|
test(`doesn't convert a ; into a : for non-PATH on Windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo;bar', 'FOO')).toBe('foo;bar')
|
expect(varValueConvert('foo;bar', 'FOO')).toBe('foo;bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts a : into a ; on Windows if PATH`, () => {
|
test(`converts a : into a ; on Windows if PATH`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo:bar', 'PATH')).toBe('foo;bar')
|
expect(varValueConvert('foo:bar', 'PATH')).toBe('foo;bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert already valid separators`, () => {
|
test(`doesn't convert already valid separators`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('foo:bar')).toBe('foo:bar')
|
expect(varValueConvert('foo:bar')).toBe('foo:bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert escaped separators on Windows if PATH`, () => {
|
test(`doesn't convert escaped separators on Windows if PATH`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo\\:bar', 'PATH')).toBe('foo:bar')
|
expect(varValueConvert('foo\\:bar', 'PATH')).toBe('foo:bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`doesn't convert escaped separators on UNIX`, () => {
|
test(`doesn't convert escaped separators on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('foo\\:bar', 'PATH')).toBe('foo:bar')
|
expect(varValueConvert('foo\\:bar', 'PATH')).toBe('foo:bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts a separator even if preceded by an escaped backslash`, () => {
|
test(`converts a separator even if preceded by an escaped backslash`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo\\\\:bar', 'PATH')).toBe('foo\\\\;bar')
|
expect(varValueConvert('foo\\\\:bar', 'PATH')).toBe('foo\\\\;bar')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`converts multiple separators if PATH`, () => {
|
test(`converts multiple separators if PATH`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo:bar:baz', 'PATH')).toBe('foo;bar;baz')
|
expect(varValueConvert('foo:bar:baz', 'PATH')).toBe('foo;bar;baz')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable value`, () => {
|
test(`resolves an env variable value`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo-$VAR1')).toBe('foo-value1')
|
expect(varValueConvert('foo-$VAR1')).toBe('foo-value1')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable value with curly syntax`, () => {
|
test(`resolves an env variable value with curly syntax`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
expect(varValueConvert('foo-${VAR1}')).toBe('foo-value1')
|
expect(varValueConvert('foo-${VAR1}')).toBe('foo-value1')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves multiple env variable values`, () => {
|
test(`resolves multiple env variable values`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo-$VAR1-$VAR2')).toBe('foo-value1-value2')
|
expect(varValueConvert('foo-$VAR1-$VAR2')).toBe('foo-value1-value2')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable value for non-existant variable`, () => {
|
test(`resolves an env variable value for non-existant variable`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('foo-$VAR_POTATO')).toBe('foo-')
|
expect(varValueConvert('foo-$VAR_POTATO')).toBe('foo-')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable with a JSON string value on Windows`, () => {
|
test(`resolves an env variable with a JSON string value on Windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('$JSON_VAR')).toBe(JSON_VALUE)
|
expect(varValueConvert('$JSON_VAR')).toBe(JSON_VALUE)
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable with a JSON string value on UNIX`, () => {
|
test(`resolves an env variable with a JSON string value on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('$JSON_VAR')).toBe(JSON_VALUE)
|
expect(varValueConvert('$JSON_VAR')).toBe(JSON_VALUE)
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`does not resolve an env variable prefixed with \\ on Windows`, () => {
|
test(`does not resolve an env variable prefixed with \\ on Windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('\\$VAR1')).toBe('$VAR1')
|
expect(varValueConvert('\\$VAR1')).toBe('$VAR1')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`does not resolve an env variable prefixed with \\ on UNIX`, () => {
|
test(`does not resolve an env variable prefixed with \\ on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('\\$VAR1')).toBe('$VAR1')
|
expect(varValueConvert('\\$VAR1')).toBe('$VAR1')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable prefixed with \\\\ on Windows`, () => {
|
test(`resolves an env variable prefixed with \\\\ on Windows`, () => {
|
||||||
isWindowsMock.__mock.returnValue = true
|
isWindowsMock.mockReturnValue(true)
|
||||||
expect(varValueConvert('\\\\$VAR1')).toBe('\\value1')
|
expect(varValueConvert('\\\\$VAR1')).toBe('\\value1')
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`resolves an env variable prefixed with \\\\ on UNIX`, () => {
|
test(`resolves an env variable prefixed with \\\\ on UNIX`, () => {
|
||||||
isWindowsMock.__mock.returnValue = false
|
isWindowsMock.mockReturnValue(false)
|
||||||
expect(varValueConvert('\\\\$VAR1')).toBe('\\value1')
|
expect(varValueConvert('\\\\$VAR1')).toBe('\\value1')
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ function parseCommand(args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getEnvVars(envSetters) {
|
function getEnvVars(envSetters) {
|
||||||
const envVars = Object.assign({}, process.env)
|
const envVars = {...process.env}
|
||||||
if (process.env.APPDATA) {
|
if (process.env.APPDATA) {
|
||||||
envVars.APPDATA = process.env.APPDATA
|
envVars.APPDATA = process.env.APPDATA
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1 +1,2 @@
|
|||||||
export default () => process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)
|
export default () =>
|
||||||
|
process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)
|
||||||
|
|||||||
Reference in New Issue
Block a user