├── .all-contributorsrc ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── bug_types.yml │ └── feature_request.yml ├── pull_request_template.md └── workflows │ └── workflow.yml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ava.config.js ├── eslint.config.js ├── gulpfile.js ├── package-lock.json ├── package.json ├── prettier.config.js ├── src ├── echo.js ├── echo.test.js ├── error.js ├── exec.js ├── exec.test.js ├── fixtures │ ├── dummy.txt │ └── dummy_two.txt ├── helpers │ ├── gulpfiles │ │ ├── exec.test.js │ │ ├── input.test.js │ │ ├── stream.test.js │ │ └── task.test.js │ ├── methods.test.js │ ├── normalize.test.js │ └── snapshot.test.js ├── input.js ├── input.test.js ├── main.d.ts ├── main.js ├── main.test-d.ts ├── options │ ├── custom.js │ ├── debug.js │ ├── debug.test.js │ ├── main.js │ └── main.test.js ├── snapshots │ └── build │ │ └── src │ │ ├── debug.test.js.md │ │ ├── debug.test.js.snap │ │ ├── echo.test.js.md │ │ ├── echo.test.js.snap │ │ ├── exec.test.js.md │ │ ├── exec.test.js.snap │ │ ├── input.test.js.md │ │ ├── input.test.js.snap │ │ ├── options.test.js.md │ │ ├── options.test.js.snap │ │ ├── options │ │ ├── debug.test.js.md │ │ ├── debug.test.js.snap │ │ ├── main.test.js.md │ │ └── main.test.js.snap │ │ ├── stream.test.js.md │ │ ├── stream.test.js.snap │ │ ├── stream │ │ ├── main.test.js.md │ │ └── main.test.js.snap │ │ ├── task.test.js.md │ │ └── task.test.js.snap ├── stream │ ├── main.js │ ├── main.test.js │ ├── options.js │ └── result.js ├── task.js └── task.test.js └── tsconfig.json /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "gulp-execa", 3 | "projectOwner": "ehmicky", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": true, 11 | "linkToUsage": false, 12 | "contributors": [ 13 | { 14 | "login": "ehmicky", 15 | "name": "ehmicky", 16 | "avatar_url": "https://avatars2.githubusercontent.com/u/8136211?v=4", 17 | "profile": "https://fosstodon.org/@ehmicky", 18 | "contributions": [ 19 | "code", 20 | "design", 21 | "ideas", 22 | "doc" 23 | ] 24 | }, 25 | { 26 | "login": "BarryThePenguin", 27 | "name": "Jonathan Haines", 28 | "avatar_url": "https://avatars3.githubusercontent.com/u/1351912?v=4", 29 | "profile": "https://twitter.com/BarryThePenguin", 30 | "contributions": [ 31 | "bug" 32 | ] 33 | } 34 | ], 35 | "contributorsPerLine": 7, 36 | "skipCi": true, 37 | "commitConvention": "none" 38 | } 39 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | max_line_length = 80 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a bug 3 | title: Please replace with a clear and descriptive title 4 | labels: [bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thanks for reporting this bug! 9 | - type: checkboxes 10 | attributes: 11 | label: Guidelines 12 | options: 13 | - label: 14 | Please search other issues to make sure this bug has not already 15 | been reported. 16 | required: true 17 | - label: 18 | If this is related to a typo or the documentation being unclear, 19 | please click on the relevant page's `Edit` button (pencil icon) and 20 | suggest a correction instead. 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: Describe the bug 25 | placeholder: A clear and concise description of what the bug is. 26 | validations: 27 | required: true 28 | - type: textarea 29 | attributes: 30 | label: Steps to reproduce 31 | placeholder: | 32 | Step-by-step instructions on how to reproduce the behavior. 33 | Example: 34 | 1. Type the following command: [...] 35 | 2. etc. 36 | validations: 37 | required: true 38 | - type: textarea 39 | attributes: 40 | label: Configuration 41 | placeholder: Command line options and/or configuration file, if any. 42 | validations: 43 | required: true 44 | - type: textarea 45 | attributes: 46 | label: Environment 47 | description: | 48 | Enter the following command in a terminal and copy/paste its output: 49 | ```bash 50 | npx envinfo --system --binaries --browsers --npmPackages gulp-execa 51 | ``` 52 | validations: 53 | required: true 54 | - type: checkboxes 55 | attributes: 56 | label: Pull request (optional) 57 | description: 58 | Pull requests are welcome! If you would like to help us fix this bug, 59 | please check our [contributions 60 | guidelines](../blob/main/CONTRIBUTING.md). 61 | options: 62 | - label: I can submit a pull request. 63 | required: false 64 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_types.yml: -------------------------------------------------------------------------------- 1 | name: Bug report (TypeScript types) 2 | description: Report a bug about TypeScript types 3 | title: Please replace with a clear and descriptive title 4 | labels: [bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thanks for reporting this bug! 9 | - type: checkboxes 10 | attributes: 11 | label: Guidelines 12 | options: 13 | - label: 14 | Please search other issues to make sure this bug has not already 15 | been reported. 16 | required: true 17 | - type: textarea 18 | attributes: 19 | label: Describe the bug 20 | placeholder: A clear and concise description of what the bug is. 21 | validations: 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: Steps to reproduce 26 | description: | 27 | Please reproduce the bug using the [TypeScript playground](https://www.typescriptlang.org/play) or [Bug workbench](https://www.typescriptlang.org/dev/bug-workbench), then paste the URL here. 28 | validations: 29 | required: true 30 | - type: textarea 31 | attributes: 32 | label: Environment 33 | description: | 34 | Enter the following command in a terminal and copy/paste its output: 35 | ```bash 36 | npx envinfo --system --binaries --browsers --npmPackages gulp-execa,typescript --npmGlobalPackages typescript 37 | ``` 38 | validations: 39 | required: true 40 | - type: checkboxes 41 | attributes: 42 | label: Pull request (optional) 43 | description: 44 | Pull requests are welcome! If you would like to help us fix this bug, 45 | please check our [contributions 46 | guidelines](../blob/main/CONTRIBUTING.md). 47 | options: 48 | - label: I can submit a pull request. 49 | required: false 50 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for this project 3 | title: Please replace with a clear and descriptive title 4 | labels: [enhancement] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Thanks for suggesting a new feature! 9 | - type: checkboxes 10 | attributes: 11 | label: Guidelines 12 | options: 13 | - label: 14 | Please search other issues to make sure this feature has not already 15 | been requested. 16 | required: true 17 | - type: textarea 18 | attributes: 19 | label: Which problem is this feature request solving? 20 | placeholder: I'm always frustrated when [...] 21 | validations: 22 | required: true 23 | - type: textarea 24 | attributes: 25 | label: Describe the solution you'd like 26 | placeholder: This could be fixed by [...] 27 | validations: 28 | required: true 29 | - type: checkboxes 30 | attributes: 31 | label: Pull request (optional) 32 | description: 33 | Pull requests are welcome! If you would like to help us fix this bug, 34 | please check our [contributions 35 | guidelines](../blob/main/CONTRIBUTING.md). 36 | options: 37 | - label: I can submit a pull request. 38 | required: false 39 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 🎉 Thanks for sending this pull request! 🎉 2 | 3 | Please make sure the title is clear and descriptive. 4 | 5 | If you are fixing a typo or documentation, please skip these instructions. 6 | 7 | Otherwise please fill in the sections below. 8 | 9 | **Which problem is this pull request solving?** 10 | 11 | Example: I'm always frustrated when [...] 12 | 13 | **List other issues or pull requests related to this problem** 14 | 15 | Example: This fixes #5012 16 | 17 | **Describe the solution you've chosen** 18 | 19 | Example: I've fixed this by [...] 20 | 21 | **Describe alternatives you've considered** 22 | 23 | Example: Another solution would be [...] 24 | 25 | **Checklist** 26 | 27 | Please add a `x` inside each checkbox: 28 | 29 | - [ ] I have read the [contribution guidelines](../blob/main/CONTRIBUTING.md). 30 | - [ ] I have added tests (we are enforcing 100% test coverage). 31 | - [ ] I have added documentation in the `README.md`, the `docs` directory (if 32 | any) 33 | - [ ] The status checks are successful (continuous integration). Those can be 34 | seen below. 35 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | jobs: 4 | combinations: 5 | uses: ehmicky/dev-tasks/.github/workflows/build.yml@main 6 | secrets: inherit 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | npm-debug.log 4 | node_modules 5 | /core 6 | .eslintcache 7 | .lycheecache 8 | .npmrc 9 | .yarn-error.log 10 | !.github/ 11 | /coverage 12 | /build 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 8.0.1 2 | 3 | ## Documentation 4 | 5 | - Improve documentation in `README.md` 6 | 7 | # 8.0.0 8 | 9 | ## Breaking changes 10 | 11 | - Drop support for Gulp 4 12 | 13 | ## Features 14 | 15 | - Support [Gulp 5](https://github.com/gulpjs/gulp/releases/tag/v5.0.0) 16 | 17 | # 7.0.1 18 | 19 | ## Dependencies 20 | 21 | - Upgrade Execa to 22 | [`9.2.0`](https://github.com/sindresorhus/execa/releases/tag/v9.2.0) 23 | 24 | # 7.0.0 25 | 26 | ## Breaking changes 27 | 28 | - Upgrade Execa to 29 | [`9.0.0`](https://github.com/sindresorhus/execa/releases/tag/v9.0.0) 30 | - Rename `verbose` option to [`debug`](README.md#debug) 31 | 32 | # 6.0.0 33 | 34 | ## Breaking changes 35 | 36 | - Minimal supported Node.js version is now `18.18.0` 37 | 38 | # 5.0.1 39 | 40 | ## Bug fixes 41 | 42 | - Fixes not being able to set the 43 | [`encoding` option](https://github.com/sindresorhus/execa/#encoding) to `null` 44 | 45 | # 5.0.0 46 | 47 | ## Breaking changes 48 | 49 | - Minimal supported Node.js version is now `16.17.0` 50 | 51 | # 4.5.0 52 | 53 | ## Features 54 | 55 | - Upgrade Execa 56 | 57 | # 4.4.1 58 | 59 | ## Bug fixes 60 | 61 | - Fix TypeScript types 62 | 63 | # 4.4.0 64 | 65 | ## Features 66 | 67 | - Improve TypeScript types 68 | 69 | # 4.3.0 70 | 71 | ## Features 72 | 73 | - Improve tree-shaking support 74 | 75 | # 4.2.0 76 | 77 | ## Features 78 | 79 | - Reduce npm package size 80 | 81 | # 4.1.0 82 | 83 | ## Features 84 | 85 | - Add TypeScript types 86 | 87 | # 4.0.0 88 | 89 | ## Breaking changes 90 | 91 | - Minimal supported Node.js version is now `14.18.0` 92 | 93 | ## Features 94 | 95 | - The [`cwd` option](https://github.com/sindresorhus/execa#cwd) can now be a URL 96 | 97 | # 3.0.2 98 | 99 | ## Bug fixes 100 | 101 | - Fix examples 102 | 103 | # 3.0.1 104 | 105 | ## Bug fixes 106 | 107 | - Fix `main` field in `package.json` 108 | 109 | # 3.0.0 110 | 111 | ## Breaking changes 112 | 113 | - Minimal supported Node.js version is now `12.20.0` 114 | - This package is now an ES module. It can only be loaded with an `import` or 115 | `import()` statement, not `require()`. See 116 | [this post for more information](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). 117 | 118 | ## Features 119 | 120 | - Improve colors detection 121 | 122 | # 2.0.0 123 | 124 | ## Breaking changes 125 | 126 | - Minimal supported Node.js version is now `10.17.0` 127 | - Add `stderr` and `stdout` to 128 | [`error.message`](https://github.com/sindresorhus/execa#message). A new 129 | property 130 | [`error.shortMessage`](https://github.com/sindresorhus/execa#shortmessage) is 131 | now available to retrieve the error message without `stderr` nor `stdout` 132 | (#397) 133 | 134 | ## Features 135 | 136 | - Upgrade to 137 | [Execa `4.0.0`](https://github.com/sindresorhus/execa/releases/tag/v4.0.0) 138 | 139 | # 1.1.0 140 | 141 | ## Features 142 | 143 | - Add 144 | [`serialization` option](https://github.com/sindresorhus/execa/blob/master/readme.md#serialization). 145 | That option was added to `child_process` methods in Node.js `13.2.0`. 146 | 147 | # 1.0.3 148 | 149 | ## Bug fixes 150 | 151 | - Default the [`all` option](https://github.com/sindresorhus/execa#all-2) to 152 | `true` when [`from: 'all'`](https://github.com/ehmicky/gulp-execa#from) is 153 | used. 154 | - Allow passing the 155 | [`execPath` Execa option](https://github.com/sindresorhus/execa#execpath) 156 | 157 | # 1.0.2 158 | 159 | ## Dependencies 160 | 161 | - [Upgrade `execa`](https://github.com/sindresorhus/execa/releases/tag/v3.0.0) 162 | 163 | # 1.0.1 164 | 165 | ## Bug fixes 166 | 167 | - Fix errors being thrown when the `detached` or `cleanup` options are used 168 | (https://github.com/sindresorhus/execa/pull/360) 169 | 170 | # 1.0.0 171 | 172 | ## Features 173 | 174 | - Upgrade to latest execa release 175 | [2.0.0](https://medium.com/@ehmicky/execa-v2-20ffafeedfdf) 176 | 177 | # 0.9.1 178 | 179 | ## Internal 180 | 181 | - Fix some tests 182 | 183 | # 0.9.0 184 | 185 | ## Internal 186 | 187 | - Only internal changes and documentation updates 188 | 189 | # 0.8.0 190 | 191 | ## Features 192 | 193 | - [`error.stdout`](https://github.com/sindresorhus/execa#stdout), 194 | [`error.stderr`](https://github.com/sindresorhus/execa#stderr) and 195 | [`error.all`](https://github.com/sindresorhus/execa#all) now contain the data 196 | that was sent before the child process exit. 197 | - If 198 | [`childProcess.kill()`](https://github.com/sindresorhus/execa#killsignal-options) 199 | does not terminate a child process after 5 seconds, force it by sending 200 | `SIGKILL`. This can be configured using the 201 | [`forceKillAftrerTimeout` option](https://github.com/sindresorhus/execa#optionsforcekillaftertimeout). 202 | - Increase [`maxBuffer`](https://github.com/sindresorhus/execa#maxbuffer) option 203 | default value from `10 MB` to `100 MB` 204 | 205 | ## Bug fixes 206 | 207 | - Ensure errors always have the same shape. 208 | 209 | # 0.7.1 210 | 211 | ## Bug fixes 212 | 213 | - Fix `npm install gulp-execa` sometimes failing (#2) 214 | 215 | # 0.7.0 216 | 217 | ## Features 218 | 219 | - Improve error messages 220 | 221 | # 0.6.1 222 | 223 | ## Bug fixes 224 | 225 | - Fix option `env` triggering process warnings 226 | 227 | # 0.6.0 228 | 229 | ## Dependencies 230 | 231 | - Remove dependency `keep-func-props` 232 | 233 | # 0.5.5 234 | 235 | ## Internal 236 | 237 | - Upgrade to latest `execa` 238 | 239 | # 0.5.4 240 | 241 | ## Bug fixes 242 | 243 | - Fix a bug where the wrong dependency version was installed. 244 | 245 | # 0.5.3 246 | 247 | ## Bug fixes 248 | 249 | - Fix bug when escaping multiple spaces with backslashes in the command. 250 | 251 | # 0.5.2 252 | 253 | ## Bug fixes 254 | 255 | - Fix error messages for `task()` on Node `>=12.3.0` 256 | 257 | # 0.5.0 258 | 259 | ## Features 260 | 261 | - The `function` passed to `stream()` can now return an object, allowing 262 | file-specific options. 263 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | This text is available in 4 | [many other languages](https://www.contributor-covenant.org/translations). 5 | 6 | ## Our Pledge 7 | 8 | We as members, contributors, and leaders pledge to make participation in our 9 | community a harassment-free experience for everyone, regardless of age, body 10 | size, visible or invisible disability, ethnicity, sex characteristics, gender 11 | identity and expression, level of experience, education, socio-economic status, 12 | nationality, personal appearance, race, religion, or sexual identity and 13 | orientation. 14 | 15 | We pledge to act and interact in ways that contribute to an open, welcoming, 16 | diverse, inclusive, and healthy community. 17 | 18 | ## Our Standards 19 | 20 | Examples of behavior that contributes to a positive environment for our 21 | community include: 22 | 23 | - Demonstrating empathy and kindness toward other people 24 | - Being respectful of differing opinions, viewpoints, and experiences 25 | - Giving and gracefully accepting constructive feedback 26 | - Accepting responsibility and apologizing to those affected by our mistakes, 27 | and learning from the experience 28 | - Focusing on what is best not just for us as individuals, but for the overall 29 | community 30 | 31 | Examples of unacceptable behavior include: 32 | 33 | - The use of sexualized language or imagery, and sexual attention or advances of 34 | any kind 35 | - Trolling, insulting or derogatory comments, and personal or political attacks 36 | - Public or private harassment 37 | - Publishing others' private information, such as a physical or email address, 38 | without their explicit permission 39 | - Other conduct which could reasonably be considered inappropriate in a 40 | professional setting 41 | 42 | ## Enforcement Responsibilities 43 | 44 | Community leaders are responsible for clarifying and enforcing our standards of 45 | acceptable behavior and will take appropriate and fair corrective action in 46 | response to any behavior that they deem inappropriate, threatening, offensive, 47 | or harmful. 48 | 49 | Community leaders have the right and responsibility to remove, edit, or reject 50 | comments, commits, code, wiki edits, issues, and other contributions that are 51 | not aligned to this Code of Conduct, and will communicate reasons for moderation 52 | decisions when appropriate. 53 | 54 | ## Scope 55 | 56 | This Code of Conduct applies within all community spaces, and also applies when 57 | an individual is officially representing the community in public spaces. 58 | Examples of representing our community include using an official e-mail address, 59 | posting via an official social media account, or acting as an appointed 60 | representative at an online or offline event. 61 | 62 | ## Enforcement 63 | 64 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 65 | reported to the community leaders responsible for enforcement at 66 | ehmicky+report@gmail.com All complaints will be reviewed and investigated 67 | promptly and fairly. 68 | 69 | All community leaders are obligated to respect the privacy and security of the 70 | reporter of any incident. 71 | 72 | ## Enforcement Guidelines 73 | 74 | Community leaders will follow these Community Impact Guidelines in determining 75 | the consequences for any action they deem in violation of this Code of Conduct: 76 | 77 | ### 1. Correction 78 | 79 | **Community Impact**: Use of inappropriate language or other behavior deemed 80 | unprofessional or unwelcome in the community. 81 | 82 | **Consequence**: A private, written warning from community leaders, providing 83 | clarity around the nature of the violation and an explanation of why the 84 | behavior was inappropriate. A public apology may be requested. 85 | 86 | ### 2. Warning 87 | 88 | **Community Impact**: A violation through a single incident or series of 89 | actions. 90 | 91 | **Consequence**: A warning with consequences for continued behavior. No 92 | interaction with the people involved, including unsolicited interaction with 93 | those enforcing the Code of Conduct, for a specified period of time. This 94 | includes avoiding interactions in community spaces as well as external channels 95 | like social media. Violating these terms may lead to a temporary or permanent 96 | ban. 97 | 98 | ### 3. Temporary Ban 99 | 100 | **Community Impact**: A serious violation of community standards, including 101 | sustained inappropriate behavior. 102 | 103 | **Consequence**: A temporary ban from any sort of interaction or public 104 | communication with the community for a specified period of time. No public or 105 | private interaction with the people involved, including unsolicited interaction 106 | with those enforcing the Code of Conduct, is allowed during this period. 107 | Violating these terms may lead to a permanent ban. 108 | 109 | ### 4. Permanent Ban 110 | 111 | **Community Impact**: Demonstrating a pattern of violation of community 112 | standards, including sustained inappropriate behavior, harassment of an 113 | individual, or aggression toward or disparagement of classes of individuals. 114 | 115 | **Consequence**: A permanent ban from any sort of public interaction within the 116 | community. 117 | 118 | ## Attribution 119 | 120 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 121 | version 2.0, available at 122 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 123 | 124 | Community Impact Guidelines were inspired by 125 | [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). 126 | 127 | [homepage]: https://www.contributor-covenant.org 128 | 129 | For answers to common questions about this code of conduct, see the FAQ at 130 | https://www.contributor-covenant.org/faq. Translations are available at 131 | https://www.contributor-covenant.org/translations. 132 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributions 2 | 3 | 🎉 Thanks for considering contributing to this project! 🎉 4 | 5 | These guidelines will help you send a pull request. 6 | 7 | If you're submitting an issue instead, please skip this document. 8 | 9 | If your pull request is related to a typo or the documentation being unclear, 10 | please click on the relevant page's `Edit` button (pencil icon) and directly 11 | suggest a correction instead. 12 | 13 | This project was made with ❤️. The simplest way to give back is by starring and 14 | sharing it online. 15 | 16 | Everyone is welcome regardless of personal background. We enforce a 17 | [Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and 18 | inclusive environment. 19 | 20 | # Development process 21 | 22 | First fork and clone the repository. If you're not sure how to do this, please 23 | watch 24 | [these videos](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github). 25 | 26 | Run: 27 | 28 | ```bash 29 | npm install 30 | ``` 31 | 32 | Make sure everything is correctly setup with: 33 | 34 | ```bash 35 | npm test 36 | ``` 37 | 38 | We use Gulp tasks to lint, test and build this project. Please check 39 | [dev-tasks](https://github.com/ehmicky/dev-tasks/blob/main/README.md) to learn 40 | how to use them. You don't need to know Gulp to use these tasks. 41 | 42 | # Requirements 43 | 44 | Our coding style is documented 45 | [here](https://github.com/ehmicky/eslint-config#coding-style). Linting and 46 | formatting should automatically handle it though. 47 | 48 | After submitting the pull request, please make sure the Continuous Integration 49 | checks are passing. 50 | 51 | We enforce 100% test coverage: each line of code must be tested. 52 | 53 | New options, methods, properties, configuration and behavior must be documented 54 | in all of these: 55 | 56 | - the `README.md` 57 | - the `docs` directory (if any) 58 | 59 | Please use the same style as the rest of the documentation and examples. 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2025 ehmicky 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | gulp-execa logo 4 | 5 | 6 | [![Node](https://img.shields.io/badge/-Node.js-808080?logo=node.js&colorA=404040&logoColor=66cc33)](https://www.npmjs.com/package/gulp-execa) 7 | [![TypeScript](https://img.shields.io/badge/-Typed-808080?logo=typescript&colorA=404040&logoColor=0096ff)](/src/main.d.ts) 8 | [![Codecov](https://img.shields.io/badge/-Tested%20100%25-808080?logo=codecov&colorA=404040)](https://codecov.io/gh/ehmicky/gulp-execa) 9 | [![Mastodon](https://img.shields.io/badge/-Mastodon-808080.svg?logo=mastodon&colorA=404040&logoColor=9590F9)](https://fosstodon.org/@ehmicky) 10 | [![Medium](https://img.shields.io/badge/-Medium-808080.svg?logo=medium&colorA=404040)](https://medium.com/@ehmicky) 11 | 12 | [Gulp.js](https://gulpjs.com) command execution for humans. 13 | 14 | As opposed to similar plugins or to 15 | [`child_process.exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback), 16 | this uses [Execa](https://github.com/sindresorhus/execa) which provides: 17 | 18 | - [Better Windows support](https://github.com/IndigoUnited/node-cross-spawn#why), 19 | including [shebangs]() 20 | - Faster and more secure commands, since [no shell is used by default](#command) 21 | - Execution of 22 | [locally installed binaries](https://github.com/sindresorhus/execa#preferlocal) 23 | - [Interleaved](https://github.com/sindresorhus/execa#all-1) `stdout`/`stderr` 24 | 25 | `gulp-execa` adds Gulp-specific features to 26 | [Execa](https://github.com/sindresorhus/execa) including: 27 | 28 | - a [task shortcut syntax](#taskcommand-options) 29 | - configurable [verbosity](#echo) 30 | - [better errors](https://github.com/gulpjs/plugin-error) 31 | 32 | Commands can be executed either directly or inside a 33 | [files stream](https://gulpjs.com/docs/en/api/src). In 34 | [streaming mode](#streamfunction-options), unlike other libraries: 35 | 36 | - commands are run [in parallel](https://github.com/almost/through2-concurrent), 37 | not [serially](https://github.com/rvagg/through2) 38 | - output can be saved [either in files or in variables](#result) 39 | 40 | # Example 41 | 42 | `gulpfile.js`: 43 | 44 | ```js 45 | import { pipeline } from 'node:stream/promises' 46 | 47 | import gulp from 'gulp' 48 | import { exec, stream, task } from 'gulp-execa' 49 | 50 | export const audit = task('npm audit') 51 | 52 | export const outdated = async () => { 53 | await exec('npm outdated') 54 | } 55 | 56 | export const sort = () => 57 | pipeline( 58 | gulp.src('*.txt'), 59 | stream(({ path }) => `sort ${path}`), 60 | gulp.dest('sorted'), 61 | ) 62 | ``` 63 | 64 | # Install 65 | 66 | ``` 67 | npm install -D gulp-execa 68 | ``` 69 | 70 | This plugin requires Gulp 5 and Node.js >=18.18.0. It is an ES module and must 71 | be loaded using 72 | [an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c), 73 | not `require()`. If TypeScript is used, it must be configured to 74 | [output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html), 75 | not CommonJS. 76 | 77 | # Methods 78 | 79 | ## task(command, [options]) 80 | 81 | Returns a Gulp task that executes `command`. 82 | 83 | ```js 84 | import { task } from 'gulp-execa' 85 | 86 | export const audit = task('npm audit') 87 | ``` 88 | 89 | ## exec(command, [options]) 90 | 91 | Executes `command`. The return value is both a promise and a 92 | [`child_process` instance](https://github.com/sindresorhus/execa#execacommand-options). 93 | 94 | The promise will be resolved with the 95 | [command result](https://github.com/sindresorhus/execa#childprocessresult). If 96 | the command failed, the promise will be rejected with a nice 97 | [error](https://github.com/sindresorhus/execa#childprocessresult). If the 98 | [`reject: false`](https://github.com/sindresorhus/execa#reject) option was used, 99 | the promise will be resolved with that error instead. 100 | 101 | ```js 102 | import { exec } from 'gulp-execa' 103 | 104 | export const outdated = async () => { 105 | await exec('npm outdated') 106 | } 107 | ``` 108 | 109 | ## stream(function, [options]) 110 | 111 | Returns a stream that executes a `command` on each input file. 112 | 113 | `function` must: 114 | 115 | - take a [Vinyl file](https://gulpjs.com/docs/en/api/vinyl#instance-properties) 116 | as argument. The most useful property is `file.path` but 117 | [other properties](https://gulpjs.com/docs/en/api/vinyl#instance-properties) 118 | are available as well. 119 | - return either: 120 | - a `command` string 121 | - an `options` object with a `command` property 122 | - `undefined` 123 | 124 | ```js 125 | import { pipeline } from 'node:stream/promises' 126 | 127 | import gulp from 'gulp' 128 | import { stream } from 'gulp-execa' 129 | 130 | export const sort = () => 131 | pipeline( 132 | gulp.src('*.txt'), 133 | stream(({ path }) => `sort ${path}`), 134 | gulp.dest('sorted'), 135 | ) 136 | ``` 137 | 138 | Each file in the stream will spawn a separate process. This can consume lots of 139 | resources so you should only use this method when there are no alternatives such 140 | as: 141 | 142 | - firing a command programmatically instead of spawning a child process 143 | - passing several files, a directory or a globbing pattern as arguments to the 144 | command 145 | 146 | The [`debug`](#debug), 147 | [`stdout`](https://github.com/sindresorhus/execa#stdout-1), 148 | [`stderr`](https://github.com/sindresorhus/execa#stderr-1), 149 | [`all`](https://github.com/sindresorhus/execa#all-2) and 150 | [`stdio`](https://github.com/sindresorhus/execa#stdio) options cannot be used 151 | with this method. 152 | 153 | # Command 154 | 155 | By default no shell interpreter (like Bash or `cmd.exe`) is used. This means 156 | `command` must be just the program and its arguments. No escaping/quoting is 157 | needed, except for significant spaces (with a backslash). 158 | 159 | Shell features such as globbing, variables and operators (like `&&` `>` `;`) 160 | should not be used. All of this can be done directly in Node.js instead. 161 | 162 | Shell interpreters are slower, less secure and less cross-platform. However, you 163 | can still opt-in to using them with the 164 | [`shell` option](https://github.com/sindresorhus/execa#shell). 165 | 166 | ```js 167 | import { writeFileStream } from 'node:fs' 168 | 169 | import gulp from 'gulp' 170 | import { task } from 'gulp-execa' 171 | 172 | // Wrong 173 | // export const check = task('npm audit && npm outdated') 174 | 175 | // Correct 176 | export const check = gulp.series(task('npm audit'), task('npm outdated')) 177 | 178 | // Wrong 179 | // export const install = task('npm install > log.txt') 180 | 181 | // Correct 182 | export const install = task('npm install', { 183 | stdout: writeFileStream('log.txt'), 184 | }) 185 | ``` 186 | 187 | # Options 188 | 189 | `options` is an optional object. 190 | 191 | [All Execa options](https://github.com/sindresorhus/execa#options) can be used. 192 | Please refer to its documentation for a list of possible options. 193 | 194 | The following options are available as well. 195 | 196 | ## echo 197 | 198 | _Type_: `boolean`\ 199 | _Default_: [`debug`](#debug) option's value 200 | 201 | Whether the `command` should be printed on the console. 202 | 203 | ```bash 204 | $ gulp audit 205 | [13:09:39] Using gulpfile ~/code/gulpfile.js 206 | [13:09:39] Starting 'audit'... 207 | [13:09:39] [gulp-execa] npm audit 208 | [13:09:44] Finished 'audit' after 4.96 s 209 | ``` 210 | 211 | ## debug 212 | 213 | _Type_: `boolean`\ 214 | _Default_: `true` for [`task()`](#taskcommand-options) and 215 | [`exec()`](#execcommand-options), `false` for 216 | [`stream()`](#streamfunction-options). 217 | 218 | Whether both the `command` and its output (`stdout`/`stderr`) should be printed 219 | on the console instead of being returned in JavaScript. 220 | 221 | ```bash 222 | $ gulp audit 223 | [13:09:39] Using gulpfile ~/code/gulpfile.js 224 | [13:09:39] Starting 'audit'... 225 | [13:09:39] [gulp-execa] npm audit 226 | 227 | == npm audit security report === 228 | 229 | found 0 vulnerabilities 230 | in 27282 scanned packages 231 | [13:09:44] Finished 'audit' after 4.96 s 232 | ``` 233 | 234 | ## result 235 | 236 | _Type_: `string`\ 237 | _Value_: `'replace'` or `'save'`\ 238 | _Default_: `'replace'` 239 | 240 | With [`stream()`](#streamfunction-options), whether the command result should: 241 | 242 | - `replace` the file's contents 243 | - `save`: [be pushed](https://github.com/sindresorhus/execa#childprocessresult) 244 | to the `file.execa` array property 245 | 246 | 247 | 248 | ```js 249 | import { pipeline } from 'node:stream/promises' 250 | 251 | import gulp from 'gulp' 252 | import { stream } from 'gulp-execa' 253 | import through from 'through2' 254 | 255 | export const task = () => 256 | pipeline( 257 | gulp.src('*.js'), 258 | // Prints the number of lines of each file 259 | stream(({ path }) => `wc -l ${path}`, { result: 'save' }), 260 | through.obj((file, encoding, func) => { 261 | console.log(file.execa[0].stdout) 262 | func(null, file) 263 | }), 264 | ) 265 | ``` 266 | 267 | ## from 268 | 269 | _Type_: `string`\ 270 | _Value_: `'stdout'`, `'stderr'` or `'all'`\ 271 | _Default_: `'stdout'` 272 | 273 | Which output stream to use with [`result: 'replace'`](#result). 274 | 275 | 276 | 277 | ```js 278 | import { pipeline } from 'node:stream/promises' 279 | 280 | import gulp from 'gulp' 281 | import { stream } from 'gulp-execa' 282 | import through from 'through2' 283 | 284 | export const task = () => 285 | pipeline( 286 | gulp.src('*.js'), 287 | // Prints the number of lines of each file, including `stderr` 288 | stream(({ path }) => `wc -l ${path}`, { result: 'replace', from: 'all' }), 289 | through.obj((file, encoding, func) => { 290 | console.log(file.contents.toString()) 291 | func(null, file) 292 | }), 293 | ) 294 | ``` 295 | 296 | ## maxConcurrency 297 | 298 | _Type_: `integer`\ 299 | _Default_: `100` 300 | 301 | With [`stream()`](#streamfunction-options), how many commands to run in parallel 302 | at once. 303 | 304 | # See also 305 | 306 | - [Execa](https://github.com/sindresorhus/execa) 307 | 308 | # Support 309 | 310 | For any question, _don't hesitate_ to [submit an issue on GitHub](../../issues). 311 | 312 | Everyone is welcome regardless of personal background. We enforce a 313 | [Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and 314 | inclusive environment. 315 | 316 | # Contributing 317 | 318 | This project was made with ❤️. The simplest way to give back is by starring and 319 | sharing it online. 320 | 321 | If the documentation is unclear or has a typo, please click on the page's `Edit` 322 | button (pencil icon) and suggest a correction. 323 | 324 | If you would like to help us fix a bug or add a new feature, please check our 325 | [guidelines](CONTRIBUTING.md). Pull requests are welcome! 326 | 327 | Thanks go to our wonderful contributors: 328 | 329 | 330 | 331 |
ehmicky
ehmicky

💻 🎨 🤔 📖
Jonathan Haines
Jonathan Haines

🐛
332 | 333 | 334 | -------------------------------------------------------------------------------- /ava.config.js: -------------------------------------------------------------------------------- 1 | export { default } from '@ehmicky/dev-tasks/ava.config.js' 2 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | export { default } from '@ehmicky/eslint-config' 2 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | export * from '@ehmicky/dev-tasks' 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-execa", 3 | "version": "8.0.1", 4 | "type": "module", 5 | "exports": { 6 | "types": "./build/src/main.d.ts", 7 | "default": "./build/src/main.js" 8 | }, 9 | "main": "./build/src/main.js", 10 | "types": "./build/src/main.d.ts", 11 | "files": [ 12 | "build/src/**/*.{js,json,d.ts}", 13 | "!build/src/**/*.test.js", 14 | "!build/src/{helpers,fixtures}" 15 | ], 16 | "sideEffects": false, 17 | "scripts": { 18 | "test": "gulp test" 19 | }, 20 | "description": "Gulp.js command execution for humans", 21 | "keywords": [ 22 | "gulp", 23 | "execa", 24 | "gulp-plugin", 25 | "gulpjs", 26 | "gulpplugin", 27 | "bash", 28 | "cli", 29 | "typescript", 30 | "es6", 31 | "javascript", 32 | "library", 33 | "nodejs", 34 | "shell", 35 | "terminal", 36 | "command-line", 37 | "child-process", 38 | "exec", 39 | "stream", 40 | "security", 41 | "spawn" 42 | ], 43 | "license": "Apache-2.0", 44 | "homepage": "https://www.github.com/ehmicky/gulp-execa", 45 | "repository": { 46 | "type": "git", 47 | "url": "git+https://github.com/ehmicky/gulp-execa.git" 48 | }, 49 | "bugs": { 50 | "url": "https://github.com/ehmicky/gulp-execa/issues" 51 | }, 52 | "author": "ehmicky (https://github.com/ehmicky)", 53 | "directories": { 54 | "lib": "src" 55 | }, 56 | "dependencies": { 57 | "@types/vinyl": "^2.0.12", 58 | "colors-option": "^6.0.1", 59 | "execa": "^9.5.2", 60 | "fancy-log": "^2.0.0", 61 | "filter-obj": "^6.1.0", 62 | "is-plain-obj": "^4.1.0", 63 | "jest-validate": "^29.7.0", 64 | "plugin-error": "^2.0.1", 65 | "rename-fn": "^2.1.0", 66 | "through2-concurrent": "^2.0.0" 67 | }, 68 | "devDependencies": { 69 | "@ehmicky/dev-tasks": "^3.0.34", 70 | "@ehmicky/eslint-config": "^20.0.32", 71 | "@ehmicky/prettier-config": "^1.0.6", 72 | "@types/node": "^22.13.14", 73 | "gulp": "^5.0.0", 74 | "raw-body": "^3.0.0", 75 | "test-each": "^7.0.1" 76 | }, 77 | "engines": { 78 | "node": ">=18.18.0" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | export { default } from '@ehmicky/prettier-config' 2 | -------------------------------------------------------------------------------- /src/echo.js: -------------------------------------------------------------------------------- 1 | import colorsOption from 'colors-option' 2 | import fancyLog from 'fancy-log' 3 | 4 | const { cyan } = colorsOption() 5 | 6 | // If `opts.echo` is `true`, echo the command and its arguments on the terminal 7 | export const printEcho = ({ input, opts: { echo } }) => { 8 | if (!echo) { 9 | return 10 | } 11 | 12 | const log = cyan.dim(`[gulp-execa] ${input}`) 13 | fancyLog(log) 14 | } 15 | -------------------------------------------------------------------------------- /src/echo.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { METHODS } from './helpers/methods.test.js' 5 | import { snapshotTest } from './helpers/snapshot.test.js' 6 | 7 | each( 8 | METHODS, 9 | [{ opts: { echo: false } }, { opts: { echo: true } }], 10 | ({ title }, methodProps, data) => 11 | test(`'echo' option | ${title}`, async (t) => { 12 | await snapshotTest({ t, methodProps, data }) 13 | }), 14 | ) 15 | -------------------------------------------------------------------------------- /src/error.js: -------------------------------------------------------------------------------- 1 | import PluginError from 'plugin-error' 2 | 3 | // Throw a Gulp error, so it prints better. 4 | // By passing `error`, we make sure `error` properties (e.g. from `execa`) 5 | // are kept. They are not printed though, as error message should be enough. 6 | export const throwError = (error, opts) => { 7 | const errorA = error instanceof Error ? error : new Error(error) 8 | 9 | if (errorA.shortMessage !== undefined) { 10 | // eslint-disable-next-line fp/no-mutation 11 | errorA.message = errorA.shortMessage 12 | // eslint-disable-next-line fp/no-delete 13 | delete errorA.shortMessage 14 | } 15 | 16 | throw new PluginError({ ...PLUGIN_ERROR_OPTS, ...opts, error: errorA }) 17 | } 18 | 19 | const PLUGIN_ERROR_OPTS = { 20 | plugin: 'gulp-execa', 21 | showProperties: false, 22 | showStack: true, 23 | } 24 | -------------------------------------------------------------------------------- /src/exec.js: -------------------------------------------------------------------------------- 1 | import { execa, parseCommandString } from 'execa' 2 | 3 | import { printEcho } from './echo.js' 4 | import { throwError } from './error.js' 5 | import { validateInput } from './input.js' 6 | import { parseOpts } from './options/main.js' 7 | 8 | // Execute a child process (command + arguments) 9 | export const exec = (input, opts) => { 10 | validateInput(input) 11 | const optsA = parseOpts({ opts }) 12 | 13 | return execCommand(input, optsA) 14 | } 15 | 16 | // Fire the command with `execaCommand()` in promise mode 17 | export const execCommand = async (input, opts) => { 18 | printEcho({ input, opts }) 19 | 20 | try { 21 | return await execaCommand(input, opts) 22 | } catch (error) { 23 | throwError(error) 24 | } 25 | } 26 | 27 | // Fire the command with `execaCommand()` in stream mode 28 | export const streamCommand = (input, opts) => { 29 | printEcho({ input, opts }) 30 | 31 | try { 32 | return execaCommand(input, opts).readable({ from: opts.from }) 33 | } catch (error) { 34 | // At the moment, `execa` never throws synchronously. 35 | // This is just a safety catch in case it has a bug. 36 | throwError(error) 37 | } 38 | } 39 | 40 | const execaCommand = (input, opts) => { 41 | const [command, ...args] = parseCommandString(input) 42 | return execa(command, args, opts) 43 | } 44 | -------------------------------------------------------------------------------- /src/exec.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { EXEC_METHODS } from './helpers/methods.test.js' 5 | import { snapshotTest } from './helpers/snapshot.test.js' 6 | 7 | each(EXEC_METHODS, [{}], ({ title }, methodProps, data) => 8 | test(`exec() | ${title}`, async (t) => { 9 | await snapshotTest({ t, methodProps, data }) 10 | }), 11 | ) 12 | -------------------------------------------------------------------------------- /src/fixtures/dummy.txt: -------------------------------------------------------------------------------- 1 | one 2 | -------------------------------------------------------------------------------- /src/fixtures/dummy_two.txt: -------------------------------------------------------------------------------- 1 | one 2 | -------------------------------------------------------------------------------- /src/helpers/gulpfiles/exec.test.js: -------------------------------------------------------------------------------- 1 | import { exec } from 'gulp-execa' 2 | 3 | import { getInput } from './input.test.js' 4 | 5 | const { command, opts } = getInput() 6 | 7 | export const main = () => exec(command, opts) 8 | -------------------------------------------------------------------------------- /src/helpers/gulpfiles/input.test.js: -------------------------------------------------------------------------------- 1 | import { env } from 'node:process' 2 | 3 | // Some information is passed by calling test to the gulpfile using the 4 | // environment variable `INPUT` 5 | export const getInput = () => { 6 | const { command, opts, buffer = true, read = true } = JSON.parse(env.INPUT) 7 | return { command, opts, buffer, read } 8 | } 9 | -------------------------------------------------------------------------------- /src/helpers/gulpfiles/stream.test.js: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'node:buffer' 2 | import { pipeline } from 'node:stream/promises' 3 | import { fileURLToPath } from 'node:url' 4 | import { callbackify } from 'node:util' 5 | 6 | import gulp from 'gulp' 7 | import { stream } from 'gulp-execa' 8 | import rawBody from 'raw-body' 9 | import through from 'through2-concurrent' 10 | 11 | import { getInput } from './input.test.js' 12 | 13 | const { command, opts, buffer, read } = getInput() 14 | 15 | const DUMMY = fileURLToPath( 16 | new URL('../../fixtures/dummy.txt', import.meta.url), 17 | ) 18 | const DUMMY_TWO = fileURLToPath( 19 | new URL('../../fixtures/dummy_two.txt', import.meta.url), 20 | ) 21 | 22 | // Task used in most tests 23 | export const main = () => 24 | pipeline( 25 | gulp.src(DUMMY, { buffer }), 26 | stream(() => command, opts), 27 | through.obj(execVinyl), 28 | ) 29 | 30 | // `input` should be an async function 31 | export const inputAsync = () => 32 | pipeline( 33 | gulp.src(DUMMY, { buffer }), 34 | stream(() => Promise.resolve(command), opts), 35 | through.obj(execVinyl), 36 | ) 37 | 38 | // `input` should be fired with the Vinyl file 39 | export const inputFile = () => 40 | pipeline( 41 | gulp.src(DUMMY, { buffer }), 42 | stream(({ basename }) => `${command} ${basename}`, opts), 43 | through.obj(execVinyl), 44 | ) 45 | 46 | const noop = () => {} 47 | 48 | // File should be skipped when returning a non-string 49 | export const inputUndefined = () => 50 | pipeline( 51 | gulp.src(DUMMY, { buffer }), 52 | stream(noop, opts), 53 | through.obj(execVinyl), 54 | ) 55 | 56 | // Should allow several files 57 | export const severalFiles = () => 58 | pipeline( 59 | gulp.src([DUMMY, DUMMY_TWO], { buffer }), 60 | stream(() => command, opts), 61 | through.obj(execVinyl), 62 | ) 63 | 64 | // Should allow doing several times 65 | export const severalTimes = () => 66 | pipeline( 67 | gulp.src(DUMMY, { buffer }), 68 | stream(() => command, opts), 69 | stream(() => command, opts), 70 | through.obj(execVinyl), 71 | ) 72 | 73 | // `input` should be a function 74 | export const inputNotFunc = () => 75 | pipeline(gulp.src(DUMMY, { buffer }), stream(command, opts)) 76 | 77 | // `input` exceptions should be propagated 78 | export const inputThrows = () => 79 | pipeline( 80 | gulp.src(DUMMY, { buffer }), 81 | stream(() => { 82 | throw new Error('error') 83 | }, opts), 84 | ) 85 | 86 | // `input` async exceptions should be propagated 87 | export const inputThrowsAsync = () => 88 | pipeline( 89 | gulp.src(DUMMY, { buffer }), 90 | stream(() => Promise.reject(new Error('error')), opts), 91 | ) 92 | 93 | const cExecVinyl = async (file) => { 94 | // When `file.contents` is a stream and an `error` event should be emitted, 95 | // we should not read the stream with `get-stream`. Otherwise Gulp will 96 | // consider the stream finished and not error. 97 | if (!read) { 98 | return file 99 | } 100 | 101 | // Prints `file.contents` so that unit test can snapshot it 102 | const string = await stringifyContents(file) 103 | // eslint-disable-next-line no-restricted-globals, no-console 104 | console.log(string) 105 | return file 106 | } 107 | 108 | const execVinyl = callbackify(cExecVinyl) 109 | 110 | // Each method must be stringified differently 111 | const stringifyContents = ({ contents, execa }) => { 112 | if (execa !== undefined) { 113 | return JSON.stringify(execa, undefined, 2) 114 | } 115 | 116 | if (Buffer.isBuffer(contents)) { 117 | return contents.toString() 118 | } 119 | 120 | // TODO: use `get-stream` once Gulp upgrade to `vinyl-fs@v4`. 121 | // See https://github.com/sindresorhus/get-stream/issues/103 122 | return rawBody(contents, { encoding: 'utf8' }) 123 | } 124 | -------------------------------------------------------------------------------- /src/helpers/gulpfiles/task.test.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp' 2 | import { task } from 'gulp-execa' 3 | 4 | import { getInput } from './input.test.js' 5 | 6 | const { command, opts } = getInput() 7 | 8 | export const main = task(command, opts) 9 | 10 | export const nested = gulp.parallel(main) 11 | -------------------------------------------------------------------------------- /src/helpers/methods.test.js: -------------------------------------------------------------------------------- 1 | // We repeat most tests for each API method 2 | export const EXEC_METHODS = [ 3 | // `exec(...)` 4 | { title: 'exec', method: 'exec' }, 5 | ] 6 | 7 | export const TASK_METHODS = [ 8 | // `task(...)` 9 | { title: 'task', method: 'task' }, 10 | ] 11 | 12 | export const STREAM_METHODS = [ 13 | // `pipeline( 14 | // gulp.src(...), 15 | // stream(..., { result: 'replace' }), 16 | // )` 17 | { title: 'stream-buffer', method: 'stream' }, 18 | // `pipeline( 19 | // gulp.src(..., { buffer: false }), 20 | // stream(..., { result: 'replace' }), 21 | // )` 22 | { title: 'stream-stream', method: 'stream', buffer: false }, 23 | // `pipeline( 24 | // gulp.src(...), 25 | // stream(..., { result: 'save' }), 26 | // )` 27 | { title: 'stream-save', method: 'stream', opts: { result: 'save' } }, 28 | ] 29 | 30 | export const METHODS = [...EXEC_METHODS, ...TASK_METHODS, ...STREAM_METHODS] 31 | -------------------------------------------------------------------------------- /src/helpers/normalize.test.js: -------------------------------------------------------------------------------- 1 | import { stripVTControlCharacters } from 'node:util' 2 | 3 | // Normalize Gulp output so it's predictable across time and environments 4 | export const normalizeMessage = (message) => { 5 | const messageA = stripVTControlCharacters(message) 6 | const messageB = REPLACEMENTS.reduce(replacePart, messageA) 7 | const messageC = messageB.trim() 8 | return messageC 9 | } 10 | 11 | const replacePart = (message, [before, after]) => message.replace(before, after) 12 | 13 | const REPLACEMENTS = [ 14 | // Windows 15 | [/\r\n/gu, '\n'], 16 | // Different exit codes across OS 17 | [/exit code 1 \(Unknown system error -1\)/gu, 'ENOENT'], 18 | [/exit code 2 \(ENOENT\)/gu, 'ENOENT'], 19 | [/spawn gulp ENOENT\n/gu, ''], 20 | // File paths 21 | [/"cwd": .*,/gu, '"cwd": /path'], 22 | [/[^ (\n]+\/[^ )\n]+/gu, '/path'], 23 | // execa errors have additional properties. 24 | // Those are printed by `util.inspect()`. However they contain `stack` and 25 | // `domainEmitter`, so we remove them. 26 | [/^([ \t]+)at [^\r\n]+\{[^]+/gmu, ''], 27 | // Node 14 prints this specific error differently 28 | [/[^]*uid" (property )?must be[^]*/gu, 'invalid options.uid'], 29 | // Node >=23 prints this warning message with Gulp 30 | [/^.*ExperimentalWarning: CommonJS module.*$/gmu, ''], 31 | [/^.*loading ES Module.*$/gmu, ''], 32 | [/^.*--trace-warnings.*$/gmu, ''], 33 | // Stack traces 34 | [/^([ \t]+)at [^\r\n]+$/gmu, '$1at STACK TRACE'], 35 | [/(([ \t]+)at STACK TRACE(\r?\n)?)+/gu, '$2at STACK TRACE$3'], 36 | [/node:.*:\d+/gu, 'node:module'], 37 | // Gulp shows file content that triggered an error 38 | [/[^]*Error:/gu, ''], 39 | // Gulp warning 40 | [/.*DEP0097.*/gu, ''], 41 | [/.*node --trace-deprecation.*/gu, ''], 42 | // Timestamps 43 | [/\[\d{2}:\d{2}:\d{2}\]/gu, '[12:00:00]'], 44 | // Duration 45 | [/(\d+\.)?\d+ (([μnm]?s)|(min))/gu, '100 ms'], 46 | [/"durationMs": .*,/gu, '"durationMs": 1,'], 47 | // Versions 48 | [/\d+\.\d+\.\d+/gu, '1.0.0'], 49 | // Make snapshots less verbose 50 | [/.*Working directory changed.*/gu, ''], 51 | [/.*Using gulpfile.*/gu, ''], 52 | ] 53 | -------------------------------------------------------------------------------- /src/helpers/snapshot.test.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'node:url' 2 | 3 | import { execa } from 'execa' 4 | 5 | import { normalizeMessage } from './normalize.test.js' 6 | 7 | const GULPFILES_DIR = fileURLToPath(new URL('gulpfiles', import.meta.url)) 8 | 9 | // Almost all unit tests follow the same principle by calling this helper: 10 | // - `gulp --gulpfile GULPFILE TASK` is fired using `execa` 11 | // - the exit code, stdout and stderr are snapshot 12 | export const snapshotTest = async ({ t, methodProps = {}, data }) => { 13 | const opts = getOpts({ methodProps, data }) 14 | const { exitCode, stdout, stderr } = await fireTask({ 15 | ...methodProps, 16 | ...data, 17 | opts, 18 | }) 19 | t.snapshot({ exitCode, stdout, stderr }) 20 | } 21 | 22 | const getOpts = ({ methodProps, data }) => { 23 | // Allows testing when `opts` is `undefined` 24 | if (methodProps.opts === undefined && data.opts === undefined) { 25 | return 26 | } 27 | 28 | return mergeOpts({ methodProps, data }) 29 | } 30 | 31 | const mergeOpts = ({ methodProps, data }) => { 32 | // Allows testing for invalid `opts` and `opts: Object.create(null)` 33 | if (data.opts === false || methodProps.opts === undefined) { 34 | return data.opts 35 | } 36 | 37 | return { ...methodProps.opts, ...data.opts } 38 | } 39 | 40 | const fireTask = async ({ 41 | // Test gulpfile to use 42 | method, 43 | // Gulp task name 44 | task = 'main', 45 | // Triggers `gulpExeca(command, opts)` 46 | command = 'echo test', 47 | opts, 48 | // With `stream()`, use `gulp.src(..., { buffer })` 49 | buffer, 50 | // See `stream()` gulpfile 51 | read, 52 | }) => { 53 | // Some information is passed to the gulpfile using the environment variable 54 | // `INPUT`, which is a JSON object. 55 | const input = JSON.stringify({ command, opts, buffer, read }) 56 | 57 | const { exitCode, stdout, stderr } = await execa( 58 | 'gulp', 59 | ['--gulpfile', `${GULPFILES_DIR}/${method}.test.js`, task], 60 | { reject: false, env: { INPUT: input } }, 61 | ) 62 | const stdoutA = normalizeMessage(stdout) 63 | const stderrA = normalizeMessage(stderr) 64 | return { exitCode, stdout: stdoutA, stderr: stderrA } 65 | } 66 | -------------------------------------------------------------------------------- /src/input.js: -------------------------------------------------------------------------------- 1 | import { throwError } from './error.js' 2 | 3 | // Validate main command and arguments 4 | export const validateInput = (input) => { 5 | if (!isValidInput(input)) { 6 | throwError(`The command must be a non-empty string: ${input}`) 7 | } 8 | } 9 | 10 | export const isValidInput = (input) => 11 | typeof input === 'string' && input.trim() !== '' 12 | -------------------------------------------------------------------------------- /src/input.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { METHODS } from './helpers/methods.test.js' 5 | import { snapshotTest } from './helpers/snapshot.test.js' 6 | 7 | each( 8 | METHODS, 9 | [{ command: true }, { command: ' ' }], 10 | ({ title }, methodProps, data) => 11 | test(`Invalid command | ${title}`, async (t) => { 12 | await snapshotTest({ t, methodProps, data }) 13 | }), 14 | ) 15 | 16 | each( 17 | METHODS, 18 | [{ opts: { uid: 0.5 } }, { command: 'node --invalid', read: false }], 19 | ({ title }, methodProps, data) => 20 | test(`Errored command | ${title}`, async (t) => { 21 | await snapshotTest({ t, methodProps, data }) 22 | }), 23 | ) 24 | -------------------------------------------------------------------------------- /src/main.d.ts: -------------------------------------------------------------------------------- 1 | import type { Transform } from 'node:stream' 2 | 3 | import type { Options as ExecaOptions, ResultPromise } from 'execa' 4 | // eslint-disable-next-line n/no-extraneous-import, @typescript-eslint/no-shadow 5 | import type File from 'vinyl' 6 | 7 | type NonStreamOptions = ExecaOptions & 8 | Readonly< 9 | Partial<{ 10 | /** 11 | * Whether the `command` should be printed on the console. 12 | * 13 | * @default `debug` option's value 14 | */ 15 | echo: boolean 16 | 17 | /** 18 | * Whether both the `command` and its output (`stdout`/`stderr`) should be 19 | * printed on the console instead of being returned in JavaScript. 20 | * 21 | * @default `true` for `task()` and `exec()`, `false` for `stream()` 22 | */ 23 | debug: boolean 24 | }> 25 | > 26 | 27 | type StreamOptions = Omit< 28 | NonStreamOptions, 29 | 'debug' | 'stdout' | 'stderr' | 'stdio' | 'all' 30 | > & 31 | Readonly< 32 | Partial<{ 33 | /** 34 | * Whether the command result should: 35 | * - `replace` the file's contents 36 | * - `save`: [be pushed](https://github.com/sindresorhus/execa#childprocessresult) 37 | * to the `file.execa` array property 38 | * 39 | * @default 'replace' 40 | * 41 | * @example 42 | * ```js 43 | * import { pipeline } from 'node:stream/promises' 44 | * 45 | * import gulp from 'gulp' 46 | * import { stream } from 'gulp-execa' 47 | * import through from 'through2' 48 | * 49 | * export const task = () => 50 | * pipeline( 51 | * gulp.src('*.js'), 52 | * // Prints the number of lines of each file 53 | * stream(({ path }) => `wc -l ${path}`, { result: 'save' }), 54 | * through.obj((file, encoding, func) => { 55 | * console.log(file.execa[0].stdout) 56 | * func(null, file) 57 | * }), 58 | * ) 59 | * ``` 60 | */ 61 | result: 'save' | 'replace' 62 | 63 | /** 64 | * Which output stream to use with `result: 'replace'`. 65 | * 66 | * @default 'stdout' 67 | * 68 | * @example 69 | * ```js 70 | * import { pipeline } from 'node:stream/promises' 71 | * 72 | * import gulp from 'gulp' 73 | * import { stream } from 'gulp-execa' 74 | * import through from 'through2' 75 | * 76 | * export const task = () => 77 | * pipeline( 78 | * gulp.src('*.js'), 79 | * // Prints the number of lines of each file, including `stderr` 80 | * stream(({ path }) => `wc -l ${path}`, { result: 'replace', from: 'all' }), 81 | * through.obj((file, encoding, func) => { 82 | * console.log(file.contents.toString()) 83 | * func(null, file) 84 | * }), 85 | * ) 86 | * ``` 87 | */ 88 | from: 'stdout' | 'stderr' | 'all' 89 | 90 | /** 91 | * How many commands to run in parallel at once. 92 | * 93 | * @default 100 94 | */ 95 | maxConcurrency: number 96 | }> 97 | > 98 | 99 | export type Options = StreamOptions & NonStreamOptions 100 | 101 | /** 102 | * Executes `command`. The return value is both a promise and a 103 | * [`child_process` instance](https://github.com/sindresorhus/execa#execacommand-options). 104 | * 105 | * The promise will be resolved with the 106 | * [command result](https://github.com/sindresorhus/execa#childprocessresult). 107 | * If the command failed, the promise will be rejected with a nice 108 | * [error](https://github.com/sindresorhus/execa#childprocessresult). 109 | * If the [`reject: false`](https://github.com/sindresorhus/execa#reject) option 110 | * was used, the promise will be resolved with that error instead. 111 | * 112 | * @example 113 | * ```js 114 | * export const outdated = async () => { 115 | * await exec('npm outdated') 116 | * } 117 | * ``` 118 | */ 119 | export function exec( 120 | command: string, 121 | options?: CallOptions, 122 | ): ResultPromise 123 | 124 | /** 125 | * Returns a Gulp task that executes `command`. 126 | * 127 | * @example 128 | * ```js 129 | * export const audit = task('npm audit') 130 | * ``` 131 | */ 132 | export function task( 133 | command: string, 134 | options?: CallOptions, 135 | ): () => ResultPromise 136 | 137 | /** 138 | * Returns a stream that executes a `command` on each input file. 139 | * 140 | * @example 141 | * ```js 142 | * import { pipeline } from 'node:stream/promises' 143 | * 144 | * import gulp from 'gulp' 145 | * import { stream } from 'gulp-execa' 146 | * 147 | * export const sort = () => 148 | * pipeline( 149 | * gulp.src('*.txt'), 150 | * stream(({ path }) => `sort ${path}`), 151 | * gulp.dest('sorted'), 152 | * ) 153 | * ``` 154 | */ 155 | export function stream( 156 | getCommand: ( 157 | file: File, 158 | ) => string | (Options & { command: string }) | undefined, 159 | options?: StreamOptions, 160 | ): Transform 161 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | export { exec } from './exec.js' 2 | export { task } from './task.js' 3 | export { stream } from './stream/main.js' 4 | -------------------------------------------------------------------------------- /src/main.test-d.ts: -------------------------------------------------------------------------------- 1 | import type { Readable, Transform } from 'node:stream' 2 | 3 | import { exec, stream, task, type Options } from 'gulp-execa' 4 | import { expectAssignable, expectNotAssignable, expectType } from 'tsd' 5 | // eslint-disable-next-line n/no-extraneous-import, @typescript-eslint/no-shadow 6 | import type File from 'vinyl' 7 | 8 | const childProcess = exec('command') 9 | expectType(childProcess.stdout) 10 | const execResult = await childProcess 11 | expectType(execResult.exitCode) 12 | 13 | const taskResult = await task('command')() 14 | expectType(taskResult.exitCode) 15 | 16 | const streamResult = stream(() => 'command') 17 | expectType(streamResult) 18 | 19 | // @ts-expect-error 20 | await exec() 21 | // @ts-expect-error 22 | task() 23 | // @ts-expect-error 24 | stream() 25 | 26 | // @ts-expect-error 27 | await exec(true) 28 | // @ts-expect-error 29 | task(true) 30 | // @ts-expect-error 31 | stream(true) 32 | 33 | stream(() => undefined) 34 | stream(() => ({ command: 'command' })) 35 | stream(() => ({ command: 'command', maxConcurrency: 0 })) 36 | // @ts-expect-error 37 | stream(() => ({ maxConcurrency: 0 })) 38 | // @ts-expect-error 39 | stream(() => ({ command: 'command', maxConcurrency: true })) 40 | // @ts-expect-error 41 | stream(() => ({ command: 'command', shell: 0 })) 42 | // @ts-expect-error 43 | stream(() => true) 44 | stream((file: File) => 'command') 45 | // @ts-expect-error 46 | stream((file: File, arg: boolean) => 'command') 47 | // @ts-expect-error 48 | stream((arg: boolean) => 'command') 49 | 50 | await exec('command', {}) 51 | task('command', {}) 52 | stream(() => 'command', {}) 53 | expectAssignable({}) 54 | // @ts-expect-error 55 | await exec('command', true) 56 | // @ts-expect-error 57 | task('command', true) 58 | // @ts-expect-error 59 | stream(() => 'command', true) 60 | expectNotAssignable(true) 61 | 62 | await exec('command', { echo: true }) 63 | task('command', { echo: true }) 64 | stream(() => 'command', { echo: true }) 65 | expectAssignable({ echo: true }) 66 | // @ts-expect-error 67 | await exec('command', { echo: 'true' }) 68 | // @ts-expect-error 69 | task('command', { echo: 'true' }) 70 | // @ts-expect-error 71 | stream(() => 'command', { echo: 'true' }) 72 | expectNotAssignable({ echo: 'true' }) 73 | 74 | await exec('command', { debug: true }) 75 | task('command', { debug: true }) 76 | // @ts-expect-error 77 | stream(() => 'command', { debug: true }) 78 | expectAssignable({ debug: true }) 79 | // @ts-expect-error 80 | await exec('command', { debug: 'true' }) 81 | // @ts-expect-error 82 | task('command', { debug: 'true' }) 83 | expectNotAssignable({ debug: 'true' }) 84 | 85 | // @ts-expect-error 86 | stream(() => 'command', { stdout: 'inherit' }) 87 | // @ts-expect-error 88 | stream(() => 'command', { stderr: 'inherit' }) 89 | // @ts-expect-error 90 | stream(() => 'command', { all: 'inherit' }) 91 | // @ts-expect-error 92 | stream(() => 'command', { stdio: 'inherit' }) 93 | 94 | stream(() => 'command', { maxConcurrency: 0 }) 95 | expectAssignable({ maxConcurrency: 0 }) 96 | // @ts-expect-error 97 | stream(() => 'command', { maxConcurrency: true }) 98 | expectNotAssignable({ maxConcurrency: true }) 99 | 100 | stream(() => 'command', { from: 'stderr' }) 101 | stream(() => 'command', { from: 'stdout' }) 102 | stream(() => 'command', { from: 'all' }) 103 | expectAssignable({ from: 'stderr' }) 104 | // @ts-expect-error 105 | stream(() => 'command', { from: 'other' }) 106 | expectNotAssignable({ from: 'other' }) 107 | 108 | stream(() => 'command', { result: 'save' }) 109 | stream(() => 'command', { result: 'replace' }) 110 | expectAssignable({ result: 'save' }) 111 | // @ts-expect-error 112 | stream(() => 'command', { result: 'other' }) 113 | expectNotAssignable({ result: 'other' }) 114 | -------------------------------------------------------------------------------- /src/options/custom.js: -------------------------------------------------------------------------------- 1 | import { throwError } from '../error.js' 2 | 3 | // Validation that cannot be handled by `jest-validate` 4 | export const validateCustom = ({ opts }) => { 5 | Object.entries(ENUM_OPTS).forEach(([attrName, allowed]) => { 6 | validateEnum({ attrName, allowed, opts }) 7 | }) 8 | } 9 | 10 | const ENUM_OPTS = { 11 | result: new Set(['save', 'replace']), 12 | from: new Set(['stdout', 'stderr', 'all']), 13 | } 14 | 15 | // Validate an enum option 16 | const validateEnum = ({ attrName, allowed, opts: { [attrName]: value } }) => { 17 | if (value === undefined || allowed.has(value)) { 18 | return 19 | } 20 | 21 | throwError( 22 | `Option '${attrName}' '${value}' must be one of: ${[...allowed].join( 23 | ', ', 24 | )}`, 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /src/options/debug.js: -------------------------------------------------------------------------------- 1 | // Translate `debug` option into `stdout|stderr|echo` options 2 | export const addDebug = ({ opts: { debug, ...opts }, opts: { stdio } }) => { 3 | if (!debug) { 4 | // The default value for `echo` must be added here, not in `DEFAULT_OPTS` 5 | return { echo: false, ...opts } 6 | } 7 | 8 | // `execa` does not allow mixing `stdio` and `stdout|stderr` options 9 | if (stdio !== undefined) { 10 | return { echo: true, ...opts } 11 | } 12 | 13 | return { stdout: 'inherit', stderr: 'inherit', echo: true, ...opts } 14 | } 15 | -------------------------------------------------------------------------------- /src/options/debug.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { METHODS } from '../helpers/methods.test.js' 5 | import { snapshotTest } from '../helpers/snapshot.test.js' 6 | 7 | each( 8 | METHODS, 9 | [ 10 | { opts: { debug: false } }, 11 | { opts: { debug: true } }, 12 | { opts: { echo: false, debug: false } }, 13 | { opts: { echo: false, debug: true } }, 14 | { opts: { echo: true, debug: false } }, 15 | { opts: { echo: true, debug: true } }, 16 | { opts: { debug: true, stdout: 'pipe', stderr: 'pipe' } }, 17 | { opts: { debug: true, stdio: 'pipe' } }, 18 | { opts: { debug: true, stdio: 'pipe', stdout: 'pipe', stderr: 'pipe' } }, 19 | ], 20 | ({ title }, methodProps, data) => 21 | // Use `serial()`, otherwise Windows CI crashes with OOM 22 | test.serial(`'debug' option | ${title}`, async (t) => { 23 | await snapshotTest({ t, methodProps, data }) 24 | }), 25 | ) 26 | -------------------------------------------------------------------------------- /src/options/main.js: -------------------------------------------------------------------------------- 1 | import { excludeKeys } from 'filter-obj' 2 | import isPlainObj from 'is-plain-obj' 3 | import { validate } from 'jest-validate' 4 | 5 | import { throwError } from '../error.js' 6 | 7 | import { validateCustom } from './custom.js' 8 | import { addDebug } from './debug.js' 9 | 10 | // Parse options 11 | export const parseOpts = ({ opts = {}, defaultOpts = {}, forcedOpts = {} }) => { 12 | validateBasic(opts) 13 | 14 | const optsA = excludeKeys(opts, isUndefined) 15 | 16 | validateOpts({ opts: optsA, defaultOpts, forcedOpts }) 17 | 18 | const optsB = { ...DEFAULT_OPTS, ...defaultOpts, ...optsA, ...forcedOpts } 19 | const optsC = addDebug({ opts: optsB }) 20 | return optsC 21 | } 22 | 23 | const validateBasic = (opts) => { 24 | if (!isPlainObj(opts)) { 25 | throwError(`Options must be a plain object: ${opts}`) 26 | } 27 | } 28 | 29 | const isUndefined = (key, value) => value === undefined 30 | 31 | const validateOpts = ({ opts, defaultOpts, forcedOpts }) => { 32 | validateCustom({ opts }) 33 | 34 | const exampleConfig = excludeKeys( 35 | { ...EXAMPLE_OPTS, ...defaultOpts }, 36 | (key) => Object.hasOwn(forcedOpts, key), 37 | ) 38 | 39 | try { 40 | // Let Execa validate its own options 41 | // eslint-disable-next-line no-empty-function 42 | validate(opts, { exampleConfig, unknown: () => {} }) 43 | } catch (error) { 44 | // `jest-validate` `error.stack` just repeats `error.message` 45 | throwError(error, { showStack: false }) 46 | } 47 | } 48 | 49 | const DEFAULT_OPTS = { 50 | debug: true, 51 | preferLocal: true, 52 | } 53 | 54 | const EXAMPLE_OPTS = { 55 | ...DEFAULT_OPTS, 56 | echo: true, 57 | } 58 | -------------------------------------------------------------------------------- /src/options/main.test.js: -------------------------------------------------------------------------------- 1 | import { dirname } from 'node:path' 2 | import { execPath } from 'node:process' 3 | 4 | import test from 'ava' 5 | import { each } from 'test-each' 6 | 7 | import { METHODS } from '../helpers/methods.test.js' 8 | import { snapshotTest } from '../helpers/snapshot.test.js' 9 | 10 | each( 11 | METHODS, 12 | [ 13 | { opts: false }, 14 | { opts: { cwd: false } }, 15 | { opts: { echo: 0 } }, 16 | { opts: { debug: 0 } }, 17 | { opts: { result: 'invalid' } }, 18 | { opts: { from: 'invalid' } }, 19 | ], 20 | ({ title }, methodProps, data) => 21 | test(`Invalid options | ${title}`, async (t) => { 22 | await snapshotTest({ t, methodProps, data }) 23 | }), 24 | ) 25 | 26 | each( 27 | [{ opts: { env: {} } }, { opts: { env: { test: true } } }], 28 | METHODS, 29 | ({ title }, data, methodProps) => 30 | test(`Valid options | ${title}`, async (t) => { 31 | await snapshotTest({ t, methodProps, data }) 32 | }), 33 | ) 34 | 35 | each(METHODS, [{}, { opts: {} }], ({ title }, methodProps, data) => 36 | test(`No options | ${title}`, async (t) => { 37 | await snapshotTest({ t, methodProps, data }) 38 | }), 39 | ) 40 | 41 | each( 42 | METHODS, 43 | [{ command: 'gulp --version', opts: { env: { PATH: dirname(execPath) } } }], 44 | ({ title }, methodProps, data) => 45 | test(`Default options | ${title}`, async (t) => { 46 | await snapshotTest({ t, methodProps, data }) 47 | }), 48 | ) 49 | -------------------------------------------------------------------------------- /src/snapshots/build/src/debug.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `src/verbose.test.js` 2 | 3 | The actual snapshot is saved in `verbose.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## 'verbose' option | exec {"opts": {"verbose": false}} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 0, 13 | stderr: '', 14 | stdout: `[12:00:00] Starting 'main'...␊ 15 | [12:00:00] Finished 'main' after 100 ms`, 16 | } 17 | 18 | ## 'verbose' option | exec {"opts": {"verbose": true}} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 0, 24 | stderr: '', 25 | stdout: `[12:00:00] Starting 'main'...␊ 26 | [12:00:00] [gulp-execa] echo test␊ 27 | test␊ 28 | [12:00:00] Finished 'main' after 100 ms`, 29 | } 30 | 31 | ## 'verbose' option | exec {"opts": {"echo": false, "verbose": false}} 32 | 33 | > Snapshot 1 34 | 35 | { 36 | exitCode: 0, 37 | stderr: '', 38 | stdout: `[12:00:00] Starting 'main'...␊ 39 | [12:00:00] Finished 'main' after 100 ms`, 40 | } 41 | 42 | ## 'verbose' option | exec {"opts": {"echo": false, "verbose": true}} 43 | 44 | > Snapshot 1 45 | 46 | { 47 | exitCode: 0, 48 | stderr: '', 49 | stdout: `[12:00:00] Starting 'main'...␊ 50 | test␊ 51 | [12:00:00] Finished 'main' after 100 ms`, 52 | } 53 | 54 | ## 'verbose' option | exec {"opts": {"echo": true, "verbose": false}} 55 | 56 | > Snapshot 1 57 | 58 | { 59 | exitCode: 0, 60 | stderr: '', 61 | stdout: `[12:00:00] Starting 'main'...␊ 62 | [12:00:00] [gulp-execa] echo test␊ 63 | [12:00:00] Finished 'main' after 100 ms`, 64 | } 65 | 66 | ## 'verbose' option | exec {"opts": {"echo": true, "verbose": true}} 67 | 68 | > Snapshot 1 69 | 70 | { 71 | exitCode: 0, 72 | stderr: '', 73 | stdout: `[12:00:00] Starting 'main'...␊ 74 | [12:00:00] [gulp-execa] echo test␊ 75 | test␊ 76 | [12:00:00] Finished 'main' after 100 ms`, 77 | } 78 | 79 | ## 'verbose' option | exec {"opts": {"stderr": "pipe", "stdout": "pipe", "verbose": true}} 80 | 81 | > Snapshot 1 82 | 83 | { 84 | exitCode: 0, 85 | stderr: '', 86 | stdout: `[12:00:00] Starting 'main'...␊ 87 | [12:00:00] [gulp-execa] echo test␊ 88 | [12:00:00] Finished 'main' after 100 ms`, 89 | } 90 | 91 | ## 'verbose' option | exec {"opts": {"stdio": "pipe", "verbose": true}} 92 | 93 | > Snapshot 1 94 | 95 | { 96 | exitCode: 0, 97 | stderr: '', 98 | stdout: `[12:00:00] Starting 'main'...␊ 99 | [12:00:00] [gulp-execa] echo test␊ 100 | [12:00:00] Finished 'main' after 100 ms`, 101 | } 102 | 103 | ## 'verbose' option | exec {"opts": {"stderr": "pipe", "stdio": "pipe", "stdout": "pipe", "verbose": true}} 104 | 105 | > Snapshot 1 106 | 107 | { 108 | exitCode: 1, 109 | stderr: `It's not possible to provide \`stdio\` in combination with one of \`stdin\`, \`stdout\`, \`stderr\`␊ 110 | at STACK TRACE`, 111 | stdout: `[12:00:00] Starting 'main'...␊ 112 | [12:00:00] [gulp-execa] echo test`, 113 | } 114 | 115 | ## 'verbose' option | task {"opts": {"verbose": false}} 116 | 117 | > Snapshot 1 118 | 119 | { 120 | exitCode: 0, 121 | stderr: '', 122 | stdout: `[12:00:00] Starting 'main'...␊ 123 | [12:00:00] Finished 'main' after 100 ms`, 124 | } 125 | 126 | ## 'verbose' option | task {"opts": {"verbose": true}} 127 | 128 | > Snapshot 1 129 | 130 | { 131 | exitCode: 0, 132 | stderr: '', 133 | stdout: `[12:00:00] Starting 'main'...␊ 134 | [12:00:00] [gulp-execa] echo test␊ 135 | test␊ 136 | [12:00:00] Finished 'main' after 100 ms`, 137 | } 138 | 139 | ## 'verbose' option | task {"opts": {"echo": false, "verbose": false}} 140 | 141 | > Snapshot 1 142 | 143 | { 144 | exitCode: 0, 145 | stderr: '', 146 | stdout: `[12:00:00] Starting 'main'...␊ 147 | [12:00:00] Finished 'main' after 100 ms`, 148 | } 149 | 150 | ## 'verbose' option | task {"opts": {"echo": false, "verbose": true}} 151 | 152 | > Snapshot 1 153 | 154 | { 155 | exitCode: 0, 156 | stderr: '', 157 | stdout: `[12:00:00] Starting 'main'...␊ 158 | test␊ 159 | [12:00:00] Finished 'main' after 100 ms`, 160 | } 161 | 162 | ## 'verbose' option | task {"opts": {"echo": true, "verbose": false}} 163 | 164 | > Snapshot 1 165 | 166 | { 167 | exitCode: 0, 168 | stderr: '', 169 | stdout: `[12:00:00] Starting 'main'...␊ 170 | [12:00:00] [gulp-execa] echo test␊ 171 | [12:00:00] Finished 'main' after 100 ms`, 172 | } 173 | 174 | ## 'verbose' option | task {"opts": {"echo": true, "verbose": true}} 175 | 176 | > Snapshot 1 177 | 178 | { 179 | exitCode: 0, 180 | stderr: '', 181 | stdout: `[12:00:00] Starting 'main'...␊ 182 | [12:00:00] [gulp-execa] echo test␊ 183 | test␊ 184 | [12:00:00] Finished 'main' after 100 ms`, 185 | } 186 | 187 | ## 'verbose' option | task {"opts": {"stderr": "pipe", "stdout": "pipe", "verbose": true}} 188 | 189 | > Snapshot 1 190 | 191 | { 192 | exitCode: 0, 193 | stderr: '', 194 | stdout: `[12:00:00] Starting 'main'...␊ 195 | [12:00:00] [gulp-execa] echo test␊ 196 | [12:00:00] Finished 'main' after 100 ms`, 197 | } 198 | 199 | ## 'verbose' option | task {"opts": {"stdio": "pipe", "verbose": true}} 200 | 201 | > Snapshot 1 202 | 203 | { 204 | exitCode: 0, 205 | stderr: '', 206 | stdout: `[12:00:00] Starting 'main'...␊ 207 | [12:00:00] [gulp-execa] echo test␊ 208 | [12:00:00] Finished 'main' after 100 ms`, 209 | } 210 | 211 | ## 'verbose' option | task {"opts": {"stderr": "pipe", "stdio": "pipe", "stdout": "pipe", "verbose": true}} 212 | 213 | > Snapshot 1 214 | 215 | { 216 | exitCode: 1, 217 | stderr: `It's not possible to provide \`stdio\` in combination with one of \`stdin\`, \`stdout\`, \`stderr\`␊ 218 | at STACK TRACE`, 219 | stdout: `[12:00:00] Starting 'main'...␊ 220 | [12:00:00] [gulp-execa] echo test`, 221 | } 222 | 223 | ## 'verbose' option | stream-buffer {"opts": {"verbose": false}} 224 | 225 | > Snapshot 1 226 | 227 | { 228 | exitCode: 0, 229 | stderr: '', 230 | stdout: `[12:00:00] Starting 'main'...␊ 231 | test␊ 232 | ␊ 233 | [12:00:00] Finished 'main' after 100 ms`, 234 | } 235 | 236 | ## 'verbose' option | stream-buffer {"opts": {"verbose": true}} 237 | 238 | > Snapshot 1 239 | 240 | { 241 | exitCode: 0, 242 | stderr: '', 243 | stdout: `[12:00:00] Starting 'main'...␊ 244 | [12:00:00] [gulp-execa] echo test␊ 245 | test␊ 246 | ␊ 247 | [12:00:00] Finished 'main' after 100 ms`, 248 | } 249 | 250 | ## 'verbose' option | stream-buffer {"opts": {"echo": false, "verbose": false}} 251 | 252 | > Snapshot 1 253 | 254 | { 255 | exitCode: 0, 256 | stderr: '', 257 | stdout: `[12:00:00] Starting 'main'...␊ 258 | test␊ 259 | ␊ 260 | [12:00:00] Finished 'main' after 100 ms`, 261 | } 262 | 263 | ## 'verbose' option | stream-buffer {"opts": {"echo": false, "verbose": true}} 264 | 265 | > Snapshot 1 266 | 267 | { 268 | exitCode: 0, 269 | stderr: '', 270 | stdout: `[12:00:00] Starting 'main'...␊ 271 | test␊ 272 | ␊ 273 | [12:00:00] Finished 'main' after 100 ms`, 274 | } 275 | 276 | ## 'verbose' option | stream-buffer {"opts": {"echo": true, "verbose": false}} 277 | 278 | > Snapshot 1 279 | 280 | { 281 | exitCode: 0, 282 | stderr: '', 283 | stdout: `[12:00:00] Starting 'main'...␊ 284 | [12:00:00] [gulp-execa] echo test␊ 285 | test␊ 286 | ␊ 287 | [12:00:00] Finished 'main' after 100 ms`, 288 | } 289 | 290 | ## 'verbose' option | stream-buffer {"opts": {"echo": true, "verbose": true}} 291 | 292 | > Snapshot 1 293 | 294 | { 295 | exitCode: 0, 296 | stderr: '', 297 | stdout: `[12:00:00] Starting 'main'...␊ 298 | [12:00:00] [gulp-execa] echo test␊ 299 | test␊ 300 | ␊ 301 | [12:00:00] Finished 'main' after 100 ms`, 302 | } 303 | 304 | ## 'verbose' option | stream-buffer {"opts": {"stderr": "pipe", "stdout": "pipe", "verbose": true}} 305 | 306 | > Snapshot 1 307 | 308 | { 309 | exitCode: 0, 310 | stderr: `● Validation Warning:␊ 311 | ␊ 312 | Unknown option "stdout" with value "pipe" was found.␊ 313 | This is probably a typing mistake. Fixing it will remove this message.␊ 314 | ␊ 315 | ● Validation Warning:␊ 316 | ␊ 317 | Unknown option "stderr" with value "pipe" was found.␊ 318 | This is probably a typing mistake. Fixing it will remove this message.`, 319 | stdout: `[12:00:00] Starting 'main'...␊ 320 | [12:00:00] [gulp-execa] echo test␊ 321 | test␊ 322 | ␊ 323 | [12:00:00] Finished 'main' after 100 ms`, 324 | } 325 | 326 | ## 'verbose' option | stream-buffer {"opts": {"stdio": "pipe", "verbose": true}} 327 | 328 | > Snapshot 1 329 | 330 | { 331 | exitCode: 0, 332 | stderr: `● Validation Warning:␊ 333 | ␊ 334 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 335 | This is probably a typing mistake. Fixing it will remove this message.`, 336 | stdout: `[12:00:00] Starting 'main'...␊ 337 | [12:00:00] [gulp-execa] echo test␊ 338 | test␊ 339 | ␊ 340 | [12:00:00] Finished 'main' after 100 ms`, 341 | } 342 | 343 | ## 'verbose' option | stream-buffer {"opts": {"stderr": "pipe", "stdio": "pipe", "stdout": "pipe", "verbose": true}} 344 | 345 | > Snapshot 1 346 | 347 | { 348 | exitCode: 0, 349 | stderr: `● Validation Warning:␊ 350 | ␊ 351 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 352 | This is probably a typing mistake. Fixing it will remove this message.␊ 353 | ␊ 354 | ● Validation Warning:␊ 355 | ␊ 356 | Unknown option "stdout" with value "pipe" was found.␊ 357 | This is probably a typing mistake. Fixing it will remove this message.␊ 358 | ␊ 359 | ● Validation Warning:␊ 360 | ␊ 361 | Unknown option "stderr" with value "pipe" was found.␊ 362 | This is probably a typing mistake. Fixing it will remove this message.`, 363 | stdout: `[12:00:00] Starting 'main'...␊ 364 | [12:00:00] [gulp-execa] echo test␊ 365 | test␊ 366 | ␊ 367 | [12:00:00] Finished 'main' after 100 ms`, 368 | } 369 | 370 | ## 'verbose' option | stream-stream {"opts": {"verbose": false}} 371 | 372 | > Snapshot 1 373 | 374 | { 375 | exitCode: 0, 376 | stderr: '', 377 | stdout: `[12:00:00] Starting 'main'...␊ 378 | test␊ 379 | ␊ 380 | [12:00:00] Finished 'main' after 100 ms`, 381 | } 382 | 383 | ## 'verbose' option | stream-stream {"opts": {"verbose": true}} 384 | 385 | > Snapshot 1 386 | 387 | { 388 | exitCode: 0, 389 | stderr: '', 390 | stdout: `[12:00:00] Starting 'main'...␊ 391 | [12:00:00] [gulp-execa] echo test␊ 392 | test␊ 393 | ␊ 394 | [12:00:00] Finished 'main' after 100 ms`, 395 | } 396 | 397 | ## 'verbose' option | stream-stream {"opts": {"echo": false, "verbose": false}} 398 | 399 | > Snapshot 1 400 | 401 | { 402 | exitCode: 0, 403 | stderr: '', 404 | stdout: `[12:00:00] Starting 'main'...␊ 405 | test␊ 406 | ␊ 407 | [12:00:00] Finished 'main' after 100 ms`, 408 | } 409 | 410 | ## 'verbose' option | stream-stream {"opts": {"echo": false, "verbose": true}} 411 | 412 | > Snapshot 1 413 | 414 | { 415 | exitCode: 0, 416 | stderr: '', 417 | stdout: `[12:00:00] Starting 'main'...␊ 418 | test␊ 419 | ␊ 420 | [12:00:00] Finished 'main' after 100 ms`, 421 | } 422 | 423 | ## 'verbose' option | stream-stream {"opts": {"echo": true, "verbose": false}} 424 | 425 | > Snapshot 1 426 | 427 | { 428 | exitCode: 0, 429 | stderr: '', 430 | stdout: `[12:00:00] Starting 'main'...␊ 431 | [12:00:00] [gulp-execa] echo test␊ 432 | test␊ 433 | ␊ 434 | [12:00:00] Finished 'main' after 100 ms`, 435 | } 436 | 437 | ## 'verbose' option | stream-stream {"opts": {"echo": true, "verbose": true}} 438 | 439 | > Snapshot 1 440 | 441 | { 442 | exitCode: 0, 443 | stderr: '', 444 | stdout: `[12:00:00] Starting 'main'...␊ 445 | [12:00:00] [gulp-execa] echo test␊ 446 | test␊ 447 | ␊ 448 | [12:00:00] Finished 'main' after 100 ms`, 449 | } 450 | 451 | ## 'verbose' option | stream-stream {"opts": {"stderr": "pipe", "stdout": "pipe", "verbose": true}} 452 | 453 | > Snapshot 1 454 | 455 | { 456 | exitCode: 0, 457 | stderr: `● Validation Warning:␊ 458 | ␊ 459 | Unknown option "stdout" with value "pipe" was found.␊ 460 | This is probably a typing mistake. Fixing it will remove this message.␊ 461 | ␊ 462 | ● Validation Warning:␊ 463 | ␊ 464 | Unknown option "stderr" with value "pipe" was found.␊ 465 | This is probably a typing mistake. Fixing it will remove this message.`, 466 | stdout: `[12:00:00] Starting 'main'...␊ 467 | [12:00:00] [gulp-execa] echo test␊ 468 | test␊ 469 | ␊ 470 | [12:00:00] Finished 'main' after 100 ms`, 471 | } 472 | 473 | ## 'verbose' option | stream-stream {"opts": {"stdio": "pipe", "verbose": true}} 474 | 475 | > Snapshot 1 476 | 477 | { 478 | exitCode: 0, 479 | stderr: `● Validation Warning:␊ 480 | ␊ 481 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 482 | This is probably a typing mistake. Fixing it will remove this message.`, 483 | stdout: `[12:00:00] Starting 'main'...␊ 484 | [12:00:00] [gulp-execa] echo test␊ 485 | test␊ 486 | ␊ 487 | [12:00:00] Finished 'main' after 100 ms`, 488 | } 489 | 490 | ## 'verbose' option | stream-stream {"opts": {"stderr": "pipe", "stdio": "pipe", "stdout": "pipe", "verbose": true}} 491 | 492 | > Snapshot 1 493 | 494 | { 495 | exitCode: 0, 496 | stderr: `● Validation Warning:␊ 497 | ␊ 498 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 499 | This is probably a typing mistake. Fixing it will remove this message.␊ 500 | ␊ 501 | ● Validation Warning:␊ 502 | ␊ 503 | Unknown option "stdout" with value "pipe" was found.␊ 504 | This is probably a typing mistake. Fixing it will remove this message.␊ 505 | ␊ 506 | ● Validation Warning:␊ 507 | ␊ 508 | Unknown option "stderr" with value "pipe" was found.␊ 509 | This is probably a typing mistake. Fixing it will remove this message.`, 510 | stdout: `[12:00:00] Starting 'main'...␊ 511 | [12:00:00] [gulp-execa] echo test␊ 512 | test␊ 513 | ␊ 514 | [12:00:00] Finished 'main' after 100 ms`, 515 | } 516 | 517 | ## 'verbose' option | stream-save {"opts": {"verbose": false}} 518 | 519 | > Snapshot 1 520 | 521 | { 522 | exitCode: 0, 523 | stderr: '', 524 | stdout: `[12:00:00] Starting 'main'...␊ 525 | [␊ 526 | {␊ 527 | "command": "echo test",␊ 528 | "escapedCommand": "echo test",␊ 529 | "exitCode": 0,␊ 530 | "stdout": "test",␊ 531 | "stderr": "",␊ 532 | "failed": false,␊ 533 | "timedOut": false,␊ 534 | "isCanceled": false,␊ 535 | "killed": false␊ 536 | }␊ 537 | ]␊ 538 | [12:00:00] Finished 'main' after 100 ms`, 539 | } 540 | 541 | ## 'verbose' option | stream-save {"opts": {"verbose": true}} 542 | 543 | > Snapshot 1 544 | 545 | { 546 | exitCode: 0, 547 | stderr: '', 548 | stdout: `[12:00:00] Starting 'main'...␊ 549 | [12:00:00] [gulp-execa] echo test␊ 550 | [␊ 551 | {␊ 552 | "command": "echo test",␊ 553 | "escapedCommand": "echo test",␊ 554 | "exitCode": 0,␊ 555 | "stdout": "test",␊ 556 | "stderr": "",␊ 557 | "failed": false,␊ 558 | "timedOut": false,␊ 559 | "isCanceled": false,␊ 560 | "killed": false␊ 561 | }␊ 562 | ]␊ 563 | [12:00:00] Finished 'main' after 100 ms`, 564 | } 565 | 566 | ## 'verbose' option | stream-save {"opts": {"echo": false, "verbose": false}} 567 | 568 | > Snapshot 1 569 | 570 | { 571 | exitCode: 0, 572 | stderr: '', 573 | stdout: `[12:00:00] Starting 'main'...␊ 574 | [␊ 575 | {␊ 576 | "command": "echo test",␊ 577 | "escapedCommand": "echo test",␊ 578 | "exitCode": 0,␊ 579 | "stdout": "test",␊ 580 | "stderr": "",␊ 581 | "failed": false,␊ 582 | "timedOut": false,␊ 583 | "isCanceled": false,␊ 584 | "killed": false␊ 585 | }␊ 586 | ]␊ 587 | [12:00:00] Finished 'main' after 100 ms`, 588 | } 589 | 590 | ## 'verbose' option | stream-save {"opts": {"echo": false, "verbose": true}} 591 | 592 | > Snapshot 1 593 | 594 | { 595 | exitCode: 0, 596 | stderr: '', 597 | stdout: `[12:00:00] Starting 'main'...␊ 598 | [␊ 599 | {␊ 600 | "command": "echo test",␊ 601 | "escapedCommand": "echo test",␊ 602 | "exitCode": 0,␊ 603 | "stdout": "test",␊ 604 | "stderr": "",␊ 605 | "failed": false,␊ 606 | "timedOut": false,␊ 607 | "isCanceled": false,␊ 608 | "killed": false␊ 609 | }␊ 610 | ]␊ 611 | [12:00:00] Finished 'main' after 100 ms`, 612 | } 613 | 614 | ## 'verbose' option | stream-save {"opts": {"echo": true, "verbose": false}} 615 | 616 | > Snapshot 1 617 | 618 | { 619 | exitCode: 0, 620 | stderr: '', 621 | stdout: `[12:00:00] Starting 'main'...␊ 622 | [12:00:00] [gulp-execa] echo test␊ 623 | [␊ 624 | {␊ 625 | "command": "echo test",␊ 626 | "escapedCommand": "echo test",␊ 627 | "exitCode": 0,␊ 628 | "stdout": "test",␊ 629 | "stderr": "",␊ 630 | "failed": false,␊ 631 | "timedOut": false,␊ 632 | "isCanceled": false,␊ 633 | "killed": false␊ 634 | }␊ 635 | ]␊ 636 | [12:00:00] Finished 'main' after 100 ms`, 637 | } 638 | 639 | ## 'verbose' option | stream-save {"opts": {"echo": true, "verbose": true}} 640 | 641 | > Snapshot 1 642 | 643 | { 644 | exitCode: 0, 645 | stderr: '', 646 | stdout: `[12:00:00] Starting 'main'...␊ 647 | [12:00:00] [gulp-execa] echo test␊ 648 | [␊ 649 | {␊ 650 | "command": "echo test",␊ 651 | "escapedCommand": "echo test",␊ 652 | "exitCode": 0,␊ 653 | "stdout": "test",␊ 654 | "stderr": "",␊ 655 | "failed": false,␊ 656 | "timedOut": false,␊ 657 | "isCanceled": false,␊ 658 | "killed": false␊ 659 | }␊ 660 | ]␊ 661 | [12:00:00] Finished 'main' after 100 ms`, 662 | } 663 | 664 | ## 'verbose' option | stream-save {"opts": {"stderr": "pipe", "stdout": "pipe", "verbose": true}} 665 | 666 | > Snapshot 1 667 | 668 | { 669 | exitCode: 0, 670 | stderr: `● Validation Warning:␊ 671 | ␊ 672 | Unknown option "stdout" with value "pipe" was found.␊ 673 | This is probably a typing mistake. Fixing it will remove this message.␊ 674 | ␊ 675 | ● Validation Warning:␊ 676 | ␊ 677 | Unknown option "stderr" with value "pipe" was found.␊ 678 | This is probably a typing mistake. Fixing it will remove this message.`, 679 | stdout: `[12:00:00] Starting 'main'...␊ 680 | [12:00:00] [gulp-execa] echo test␊ 681 | [␊ 682 | {␊ 683 | "command": "echo test",␊ 684 | "escapedCommand": "echo test",␊ 685 | "exitCode": 0,␊ 686 | "stdout": "test",␊ 687 | "stderr": "",␊ 688 | "failed": false,␊ 689 | "timedOut": false,␊ 690 | "isCanceled": false,␊ 691 | "killed": false␊ 692 | }␊ 693 | ]␊ 694 | [12:00:00] Finished 'main' after 100 ms`, 695 | } 696 | 697 | ## 'verbose' option | stream-save {"opts": {"stdio": "pipe", "verbose": true}} 698 | 699 | > Snapshot 1 700 | 701 | { 702 | exitCode: 0, 703 | stderr: `● Validation Warning:␊ 704 | ␊ 705 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 706 | This is probably a typing mistake. Fixing it will remove this message.`, 707 | stdout: `[12:00:00] Starting 'main'...␊ 708 | [12:00:00] [gulp-execa] echo test␊ 709 | [␊ 710 | {␊ 711 | "command": "echo test",␊ 712 | "escapedCommand": "echo test",␊ 713 | "exitCode": 0,␊ 714 | "stdout": "test",␊ 715 | "stderr": "",␊ 716 | "failed": false,␊ 717 | "timedOut": false,␊ 718 | "isCanceled": false,␊ 719 | "killed": false␊ 720 | }␊ 721 | ]␊ 722 | [12:00:00] Finished 'main' after 100 ms`, 723 | } 724 | 725 | ## 'verbose' option | stream-save {"opts": {"stderr": "pipe", "stdio": "pipe", "stdout": "pipe", "verbose": true}} 726 | 727 | > Snapshot 1 728 | 729 | { 730 | exitCode: 0, 731 | stderr: `● Validation Warning:␊ 732 | ␊ 733 | Unknown option "stdio" with value "pipe" was found. Did you mean "stdin"?␊ 734 | This is probably a typing mistake. Fixing it will remove this message.␊ 735 | ␊ 736 | ● Validation Warning:␊ 737 | ␊ 738 | Unknown option "stdout" with value "pipe" was found.␊ 739 | This is probably a typing mistake. Fixing it will remove this message.␊ 740 | ␊ 741 | ● Validation Warning:␊ 742 | ␊ 743 | Unknown option "stderr" with value "pipe" was found.␊ 744 | This is probably a typing mistake. Fixing it will remove this message.`, 745 | stdout: `[12:00:00] Starting 'main'...␊ 746 | [12:00:00] [gulp-execa] echo test␊ 747 | [␊ 748 | {␊ 749 | "command": "echo test",␊ 750 | "escapedCommand": "echo test",␊ 751 | "exitCode": 0,␊ 752 | "stdout": "test",␊ 753 | "stderr": "",␊ 754 | "failed": false,␊ 755 | "timedOut": false,␊ 756 | "isCanceled": false,␊ 757 | "killed": false␊ 758 | }␊ 759 | ]␊ 760 | [12:00:00] Finished 'main' after 100 ms`, 761 | } 762 | -------------------------------------------------------------------------------- /src/snapshots/build/src/debug.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/debug.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/echo.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/echo.test.js` 2 | 3 | The actual snapshot is saved in `echo.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## 'echo' option | exec {"opts": {"echo": false}} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 0, 13 | stderr: '', 14 | stdout: `[12:00:00] Starting 'main'...␊ 15 | test␊ 16 | [12:00:00] Finished 'main' after 100 ms`, 17 | } 18 | 19 | ## 'echo' option | exec {"opts": {"echo": true}} 20 | 21 | > Snapshot 1 22 | 23 | { 24 | exitCode: 0, 25 | stderr: '', 26 | stdout: `[12:00:00] Starting 'main'...␊ 27 | [12:00:00] [gulp-execa] echo test␊ 28 | test␊ 29 | [12:00:00] Finished 'main' after 100 ms`, 30 | } 31 | 32 | ## 'echo' option | task {"opts": {"echo": false}} 33 | 34 | > Snapshot 1 35 | 36 | { 37 | exitCode: 0, 38 | stderr: '', 39 | stdout: `[12:00:00] Starting 'main'...␊ 40 | test␊ 41 | [12:00:00] Finished 'main' after 100 ms`, 42 | } 43 | 44 | ## 'echo' option | task {"opts": {"echo": true}} 45 | 46 | > Snapshot 1 47 | 48 | { 49 | exitCode: 0, 50 | stderr: '', 51 | stdout: `[12:00:00] Starting 'main'...␊ 52 | [12:00:00] [gulp-execa] echo test␊ 53 | test␊ 54 | [12:00:00] Finished 'main' after 100 ms`, 55 | } 56 | 57 | ## 'echo' option | stream-buffer {"opts": {"echo": false}} 58 | 59 | > Snapshot 1 60 | 61 | { 62 | exitCode: 0, 63 | stderr: '', 64 | stdout: `[12:00:00] Starting 'main'...␊ 65 | test␊ 66 | ␊ 67 | [12:00:00] Finished 'main' after 100 ms`, 68 | } 69 | 70 | ## 'echo' option | stream-buffer {"opts": {"echo": true}} 71 | 72 | > Snapshot 1 73 | 74 | { 75 | exitCode: 0, 76 | stderr: '', 77 | stdout: `[12:00:00] Starting 'main'...␊ 78 | [12:00:00] [gulp-execa] echo test␊ 79 | test␊ 80 | ␊ 81 | [12:00:00] Finished 'main' after 100 ms`, 82 | } 83 | 84 | ## 'echo' option | stream-stream {"opts": {"echo": false}} 85 | 86 | > Snapshot 1 87 | 88 | { 89 | exitCode: 0, 90 | stderr: '', 91 | stdout: `[12:00:00] Starting 'main'...␊ 92 | test␊ 93 | ␊ 94 | [12:00:00] Finished 'main' after 100 ms`, 95 | } 96 | 97 | ## 'echo' option | stream-stream {"opts": {"echo": true}} 98 | 99 | > Snapshot 1 100 | 101 | { 102 | exitCode: 0, 103 | stderr: '', 104 | stdout: `[12:00:00] Starting 'main'...␊ 105 | [12:00:00] [gulp-execa] echo test␊ 106 | test␊ 107 | ␊ 108 | [12:00:00] Finished 'main' after 100 ms`, 109 | } 110 | 111 | ## 'echo' option | stream-save {"opts": {"echo": false}} 112 | 113 | > Snapshot 1 114 | 115 | { 116 | exitCode: 0, 117 | stderr: '', 118 | stdout: `[12:00:00] Starting 'main'...␊ 119 | [␊ 120 | {␊ 121 | "command": "echo test",␊ 122 | "escapedCommand": "echo test",␊ 123 | "cwd": /path␊ 124 | "durationMs": 1,␊ 125 | "failed": false,␊ 126 | "timedOut": false,␊ 127 | "isCanceled": false,␊ 128 | "isGracefullyCanceled": false,␊ 129 | "isTerminated": false,␊ 130 | "isMaxBuffer": false,␊ 131 | "isForcefullyTerminated": false,␊ 132 | "exitCode": 0,␊ 133 | "stdout": "test",␊ 134 | "stderr": "",␊ 135 | "stdio": [␊ 136 | null,␊ 137 | "test",␊ 138 | ""␊ 139 | ],␊ 140 | "ipcOutput": [],␊ 141 | "pipedFrom": []␊ 142 | }␊ 143 | ]␊ 144 | [12:00:00] Finished 'main' after 100 ms`, 145 | } 146 | 147 | ## 'echo' option | stream-save {"opts": {"echo": true}} 148 | 149 | > Snapshot 1 150 | 151 | { 152 | exitCode: 0, 153 | stderr: '', 154 | stdout: `[12:00:00] Starting 'main'...␊ 155 | [12:00:00] [gulp-execa] echo test␊ 156 | [␊ 157 | {␊ 158 | "command": "echo test",␊ 159 | "escapedCommand": "echo test",␊ 160 | "cwd": /path␊ 161 | "durationMs": 1,␊ 162 | "failed": false,␊ 163 | "timedOut": false,␊ 164 | "isCanceled": false,␊ 165 | "isGracefullyCanceled": false,␊ 166 | "isTerminated": false,␊ 167 | "isMaxBuffer": false,␊ 168 | "isForcefullyTerminated": false,␊ 169 | "exitCode": 0,␊ 170 | "stdout": "test",␊ 171 | "stderr": "",␊ 172 | "stdio": [␊ 173 | null,␊ 174 | "test",␊ 175 | ""␊ 176 | ],␊ 177 | "ipcOutput": [],␊ 178 | "pipedFrom": []␊ 179 | }␊ 180 | ]␊ 181 | [12:00:00] Finished 'main' after 100 ms`, 182 | } 183 | -------------------------------------------------------------------------------- /src/snapshots/build/src/echo.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/echo.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/exec.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/exec.test.js` 2 | 3 | The actual snapshot is saved in `exec.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## exec() | exec {} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 0, 13 | stderr: '', 14 | stdout: `[12:00:00] Starting 'main'...␊ 15 | [12:00:00] [gulp-execa] echo test␊ 16 | test␊ 17 | [12:00:00] Finished 'main' after 100 ms`, 18 | } 19 | -------------------------------------------------------------------------------- /src/snapshots/build/src/exec.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/exec.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/input.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/input.test.js` 2 | 3 | The actual snapshot is saved in `input.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## Invalid command | exec {"command": true} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 1, 13 | stderr: `The command must be a non-empty string: true␊ 14 | at STACK TRACE`, 15 | stdout: '[12:00:00] Starting \'main\'...', 16 | } 17 | 18 | ## Invalid command | exec {"command": " "} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 1, 24 | stderr: `The command must be a non-empty string: ␊ 25 | at STACK TRACE`, 26 | stdout: '[12:00:00] Starting \'main\'...', 27 | } 28 | 29 | ## Invalid command | task {"command": true} 30 | 31 | > Snapshot 1 32 | 33 | { 34 | exitCode: 1, 35 | stderr: `The command must be a non-empty string: true␊ 36 | at STACK TRACE`, 37 | stdout: '', 38 | } 39 | 40 | ## Invalid command | task {"command": " "} 41 | 42 | > Snapshot 1 43 | 44 | { 45 | exitCode: 1, 46 | stderr: `The command must be a non-empty string: ␊ 47 | at STACK TRACE`, 48 | stdout: '', 49 | } 50 | 51 | ## Invalid command | stream-buffer {"command": true} 52 | 53 | > Snapshot 1 54 | 55 | { 56 | exitCode: 0, 57 | stderr: '', 58 | stdout: `[12:00:00] Starting 'main'...␊ 59 | one␊ 60 | ␊ 61 | [12:00:00] Finished 'main' after 100 ms`, 62 | } 63 | 64 | ## Invalid command | stream-buffer {"command": " "} 65 | 66 | > Snapshot 1 67 | 68 | { 69 | exitCode: 0, 70 | stderr: '', 71 | stdout: `[12:00:00] Starting 'main'...␊ 72 | one␊ 73 | ␊ 74 | [12:00:00] Finished 'main' after 100 ms`, 75 | } 76 | 77 | ## Invalid command | stream-stream {"command": true} 78 | 79 | > Snapshot 1 80 | 81 | { 82 | exitCode: 0, 83 | stderr: '', 84 | stdout: `[12:00:00] Starting 'main'...␊ 85 | one␊ 86 | ␊ 87 | [12:00:00] Finished 'main' after 100 ms`, 88 | } 89 | 90 | ## Invalid command | stream-stream {"command": " "} 91 | 92 | > Snapshot 1 93 | 94 | { 95 | exitCode: 0, 96 | stderr: '', 97 | stdout: `[12:00:00] Starting 'main'...␊ 98 | one␊ 99 | ␊ 100 | [12:00:00] Finished 'main' after 100 ms`, 101 | } 102 | 103 | ## Invalid command | stream-save {"command": true} 104 | 105 | > Snapshot 1 106 | 107 | { 108 | exitCode: 0, 109 | stderr: '', 110 | stdout: `[12:00:00] Starting 'main'...␊ 111 | []␊ 112 | [12:00:00] Finished 'main' after 100 ms`, 113 | } 114 | 115 | ## Invalid command | stream-save {"command": " "} 116 | 117 | > Snapshot 1 118 | 119 | { 120 | exitCode: 0, 121 | stderr: '', 122 | stdout: `[12:00:00] Starting 'main'...␊ 123 | []␊ 124 | [12:00:00] Finished 'main' after 100 ms`, 125 | } 126 | 127 | ## Errored command | exec {"opts": {"uid": 0.5}} 128 | 129 | > Snapshot 1 130 | 131 | { 132 | exitCode: 1, 133 | stderr: 'invalid options.uid', 134 | stdout: `[12:00:00] Starting 'main'...␊ 135 | [12:00:00] [gulp-execa] echo test`, 136 | } 137 | 138 | ## Errored command | exec {"command": "node --invalid", "read": false} 139 | 140 | > Snapshot 1 141 | 142 | { 143 | exitCode: 1, 144 | stderr: `Command failed with exit code 9: node --invalid␊ 145 | at STACK TRACE`, 146 | stdout: `[12:00:00] Starting 'main'...␊ 147 | [12:00:00] [gulp-execa] node --invalid`, 148 | } 149 | 150 | ## Errored command | task {"opts": {"uid": 0.5}} 151 | 152 | > Snapshot 1 153 | 154 | { 155 | exitCode: 1, 156 | stderr: 'invalid options.uid', 157 | stdout: `[12:00:00] Starting 'main'...␊ 158 | [12:00:00] [gulp-execa] echo test`, 159 | } 160 | 161 | ## Errored command | task {"command": "node --invalid", "read": false} 162 | 163 | > Snapshot 1 164 | 165 | { 166 | exitCode: 1, 167 | stderr: `Command failed with exit code 9: node --invalid␊ 168 | at STACK TRACE`, 169 | stdout: `[12:00:00] Starting 'main'...␊ 170 | [12:00:00] [gulp-execa] node --invalid`, 171 | } 172 | 173 | ## Errored command | stream-buffer {"opts": {"uid": 0.5}} 174 | 175 | > Snapshot 1 176 | 177 | { 178 | exitCode: 1, 179 | stderr: 'invalid options.uid', 180 | stdout: '[12:00:00] Starting \'main\'...', 181 | } 182 | 183 | ## Errored command | stream-buffer {"command": "node --invalid", "read": false} 184 | 185 | > Snapshot 1 186 | 187 | { 188 | exitCode: 1, 189 | stderr: `Command failed with exit code 9: node --invalid␊ 190 | at STACK TRACE`, 191 | stdout: '[12:00:00] Starting \'main\'...', 192 | } 193 | 194 | ## Errored command | stream-stream {"opts": {"uid": 0.5}} 195 | 196 | > Snapshot 1 197 | 198 | { 199 | exitCode: 1, 200 | stderr: 'invalid options.uid', 201 | stdout: '[12:00:00] Starting \'main\'...', 202 | } 203 | 204 | ## Errored command | stream-stream {"command": "node --invalid", "read": false} 205 | 206 | > Snapshot 1 207 | 208 | { 209 | exitCode: 1, 210 | stderr: `Command failed with exit code 9: node --invalid␊ 211 | ␊ 212 | node: bad option: --invalid␊ 213 | at STACK TRACE␊ 214 | Emitted 'error' event on Domain instance at:␊ 215 | at STACK TRACE`, 216 | stdout: `[12:00:00] Starting 'main'...␊ 217 | [12:00:00] Finished 'main' after 100 ms`, 218 | } 219 | 220 | ## Errored command | stream-save {"opts": {"uid": 0.5}} 221 | 222 | > Snapshot 1 223 | 224 | { 225 | exitCode: 1, 226 | stderr: 'invalid options.uid', 227 | stdout: '[12:00:00] Starting \'main\'...', 228 | } 229 | 230 | ## Errored command | stream-save {"command": "node --invalid", "read": false} 231 | 232 | > Snapshot 1 233 | 234 | { 235 | exitCode: 1, 236 | stderr: `Command failed with exit code 9: node --invalid␊ 237 | at STACK TRACE`, 238 | stdout: '[12:00:00] Starting \'main\'...', 239 | } 240 | -------------------------------------------------------------------------------- /src/snapshots/build/src/input.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/input.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/options.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/options.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/options/debug.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/options/debug.test.js` 2 | 3 | The actual snapshot is saved in `debug.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## 'debug' option | exec {"opts": {"debug": false}} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 0, 13 | stderr: '', 14 | stdout: `[12:00:00] Starting 'main'...␊ 15 | [12:00:00] Finished 'main' after 100 ms`, 16 | } 17 | 18 | ## 'debug' option | exec {"opts": {"debug": true}} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 0, 24 | stderr: '', 25 | stdout: `[12:00:00] Starting 'main'...␊ 26 | [12:00:00] [gulp-execa] echo test␊ 27 | test␊ 28 | [12:00:00] Finished 'main' after 100 ms`, 29 | } 30 | 31 | ## 'debug' option | exec {"opts": {"debug": false, "echo": false}} 32 | 33 | > Snapshot 1 34 | 35 | { 36 | exitCode: 0, 37 | stderr: '', 38 | stdout: `[12:00:00] Starting 'main'...␊ 39 | [12:00:00] Finished 'main' after 100 ms`, 40 | } 41 | 42 | ## 'debug' option | exec {"opts": {"debug": true, "echo": false}} 43 | 44 | > Snapshot 1 45 | 46 | { 47 | exitCode: 0, 48 | stderr: '', 49 | stdout: `[12:00:00] Starting 'main'...␊ 50 | test␊ 51 | [12:00:00] Finished 'main' after 100 ms`, 52 | } 53 | 54 | ## 'debug' option | exec {"opts": {"debug": false, "echo": true}} 55 | 56 | > Snapshot 1 57 | 58 | { 59 | exitCode: 0, 60 | stderr: '', 61 | stdout: `[12:00:00] Starting 'main'...␊ 62 | [12:00:00] [gulp-execa] echo test␊ 63 | [12:00:00] Finished 'main' after 100 ms`, 64 | } 65 | 66 | ## 'debug' option | exec {"opts": {"debug": true, "echo": true}} 67 | 68 | > Snapshot 1 69 | 70 | { 71 | exitCode: 0, 72 | stderr: '', 73 | stdout: `[12:00:00] Starting 'main'...␊ 74 | [12:00:00] [gulp-execa] echo test␊ 75 | test␊ 76 | [12:00:00] Finished 'main' after 100 ms`, 77 | } 78 | 79 | ## 'debug' option | exec {"opts": {"debug": true, "stderr": "pipe", "stdout": "pipe"}} 80 | 81 | > Snapshot 1 82 | 83 | { 84 | exitCode: 0, 85 | stderr: '', 86 | stdout: `[12:00:00] Starting 'main'...␊ 87 | [12:00:00] [gulp-execa] echo test␊ 88 | [12:00:00] Finished 'main' after 100 ms`, 89 | } 90 | 91 | ## 'debug' option | exec {"opts": {"debug": true, "stdio": "pipe"}} 92 | 93 | > Snapshot 1 94 | 95 | { 96 | exitCode: 0, 97 | stderr: '', 98 | stdout: `[12:00:00] Starting 'main'...␊ 99 | [12:00:00] [gulp-execa] echo test␊ 100 | [12:00:00] Finished 'main' after 100 ms`, 101 | } 102 | 103 | ## 'debug' option | exec {"opts": {"debug": true, "stderr": "pipe", "stdio": "pipe", "stdout": "pipe"}} 104 | 105 | > Snapshot 1 106 | 107 | { 108 | exitCode: 1, 109 | stderr: `It's not possible to provide \`stdio\` in combination with one of \`stdin\`, \`stdout\`, \`stderr\`␊ 110 | at STACK TRACE`, 111 | stdout: `[12:00:00] Starting 'main'...␊ 112 | [12:00:00] [gulp-execa] echo test`, 113 | } 114 | 115 | ## 'debug' option | task {"opts": {"debug": false}} 116 | 117 | > Snapshot 1 118 | 119 | { 120 | exitCode: 0, 121 | stderr: '', 122 | stdout: `[12:00:00] Starting 'main'...␊ 123 | [12:00:00] Finished 'main' after 100 ms`, 124 | } 125 | 126 | ## 'debug' option | task {"opts": {"debug": true}} 127 | 128 | > Snapshot 1 129 | 130 | { 131 | exitCode: 0, 132 | stderr: '', 133 | stdout: `[12:00:00] Starting 'main'...␊ 134 | [12:00:00] [gulp-execa] echo test␊ 135 | test␊ 136 | [12:00:00] Finished 'main' after 100 ms`, 137 | } 138 | 139 | ## 'debug' option | task {"opts": {"debug": false, "echo": false}} 140 | 141 | > Snapshot 1 142 | 143 | { 144 | exitCode: 0, 145 | stderr: '', 146 | stdout: `[12:00:00] Starting 'main'...␊ 147 | [12:00:00] Finished 'main' after 100 ms`, 148 | } 149 | 150 | ## 'debug' option | task {"opts": {"debug": true, "echo": false}} 151 | 152 | > Snapshot 1 153 | 154 | { 155 | exitCode: 0, 156 | stderr: '', 157 | stdout: `[12:00:00] Starting 'main'...␊ 158 | test␊ 159 | [12:00:00] Finished 'main' after 100 ms`, 160 | } 161 | 162 | ## 'debug' option | task {"opts": {"debug": false, "echo": true}} 163 | 164 | > Snapshot 1 165 | 166 | { 167 | exitCode: 0, 168 | stderr: '', 169 | stdout: `[12:00:00] Starting 'main'...␊ 170 | [12:00:00] [gulp-execa] echo test␊ 171 | [12:00:00] Finished 'main' after 100 ms`, 172 | } 173 | 174 | ## 'debug' option | task {"opts": {"debug": true, "echo": true}} 175 | 176 | > Snapshot 1 177 | 178 | { 179 | exitCode: 0, 180 | stderr: '', 181 | stdout: `[12:00:00] Starting 'main'...␊ 182 | [12:00:00] [gulp-execa] echo test␊ 183 | test␊ 184 | [12:00:00] Finished 'main' after 100 ms`, 185 | } 186 | 187 | ## 'debug' option | task {"opts": {"debug": true, "stderr": "pipe", "stdout": "pipe"}} 188 | 189 | > Snapshot 1 190 | 191 | { 192 | exitCode: 0, 193 | stderr: '', 194 | stdout: `[12:00:00] Starting 'main'...␊ 195 | [12:00:00] [gulp-execa] echo test␊ 196 | [12:00:00] Finished 'main' after 100 ms`, 197 | } 198 | 199 | ## 'debug' option | task {"opts": {"debug": true, "stdio": "pipe"}} 200 | 201 | > Snapshot 1 202 | 203 | { 204 | exitCode: 0, 205 | stderr: '', 206 | stdout: `[12:00:00] Starting 'main'...␊ 207 | [12:00:00] [gulp-execa] echo test␊ 208 | [12:00:00] Finished 'main' after 100 ms`, 209 | } 210 | 211 | ## 'debug' option | task {"opts": {"debug": true, "stderr": "pipe", "stdio": "pipe", "stdout": "pipe"}} 212 | 213 | > Snapshot 1 214 | 215 | { 216 | exitCode: 1, 217 | stderr: `It's not possible to provide \`stdio\` in combination with one of \`stdin\`, \`stdout\`, \`stderr\`␊ 218 | at STACK TRACE`, 219 | stdout: `[12:00:00] Starting 'main'...␊ 220 | [12:00:00] [gulp-execa] echo test`, 221 | } 222 | 223 | ## 'debug' option | stream-buffer {"opts": {"debug": false}} 224 | 225 | > Snapshot 1 226 | 227 | { 228 | exitCode: 0, 229 | stderr: '', 230 | stdout: `[12:00:00] Starting 'main'...␊ 231 | test␊ 232 | ␊ 233 | [12:00:00] Finished 'main' after 100 ms`, 234 | } 235 | 236 | ## 'debug' option | stream-buffer {"opts": {"debug": true}} 237 | 238 | > Snapshot 1 239 | 240 | { 241 | exitCode: 0, 242 | stderr: '', 243 | stdout: `[12:00:00] Starting 'main'...␊ 244 | [12:00:00] [gulp-execa] echo test␊ 245 | test␊ 246 | ␊ 247 | [12:00:00] Finished 'main' after 100 ms`, 248 | } 249 | 250 | ## 'debug' option | stream-buffer {"opts": {"debug": false, "echo": false}} 251 | 252 | > Snapshot 1 253 | 254 | { 255 | exitCode: 0, 256 | stderr: '', 257 | stdout: `[12:00:00] Starting 'main'...␊ 258 | test␊ 259 | ␊ 260 | [12:00:00] Finished 'main' after 100 ms`, 261 | } 262 | 263 | ## 'debug' option | stream-buffer {"opts": {"debug": true, "echo": false}} 264 | 265 | > Snapshot 1 266 | 267 | { 268 | exitCode: 0, 269 | stderr: '', 270 | stdout: `[12:00:00] Starting 'main'...␊ 271 | test␊ 272 | ␊ 273 | [12:00:00] Finished 'main' after 100 ms`, 274 | } 275 | 276 | ## 'debug' option | stream-buffer {"opts": {"debug": false, "echo": true}} 277 | 278 | > Snapshot 1 279 | 280 | { 281 | exitCode: 0, 282 | stderr: '', 283 | stdout: `[12:00:00] Starting 'main'...␊ 284 | [12:00:00] [gulp-execa] echo test␊ 285 | test␊ 286 | ␊ 287 | [12:00:00] Finished 'main' after 100 ms`, 288 | } 289 | 290 | ## 'debug' option | stream-buffer {"opts": {"debug": true, "echo": true}} 291 | 292 | > Snapshot 1 293 | 294 | { 295 | exitCode: 0, 296 | stderr: '', 297 | stdout: `[12:00:00] Starting 'main'...␊ 298 | [12:00:00] [gulp-execa] echo test␊ 299 | test␊ 300 | ␊ 301 | [12:00:00] Finished 'main' after 100 ms`, 302 | } 303 | 304 | ## 'debug' option | stream-buffer {"opts": {"debug": true, "stderr": "pipe", "stdout": "pipe"}} 305 | 306 | > Snapshot 1 307 | 308 | { 309 | exitCode: 0, 310 | stderr: '', 311 | stdout: `[12:00:00] Starting 'main'...␊ 312 | [12:00:00] [gulp-execa] echo test␊ 313 | test␊ 314 | ␊ 315 | [12:00:00] Finished 'main' after 100 ms`, 316 | } 317 | 318 | ## 'debug' option | stream-buffer {"opts": {"debug": true, "stdio": "pipe"}} 319 | 320 | > Snapshot 1 321 | 322 | { 323 | exitCode: 0, 324 | stderr: '', 325 | stdout: `[12:00:00] Starting 'main'...␊ 326 | [12:00:00] [gulp-execa] echo test␊ 327 | test␊ 328 | ␊ 329 | [12:00:00] Finished 'main' after 100 ms`, 330 | } 331 | 332 | ## 'debug' option | stream-buffer {"opts": {"debug": true, "stderr": "pipe", "stdio": "pipe", "stdout": "pipe"}} 333 | 334 | > Snapshot 1 335 | 336 | { 337 | exitCode: 0, 338 | stderr: '', 339 | stdout: `[12:00:00] Starting 'main'...␊ 340 | [12:00:00] [gulp-execa] echo test␊ 341 | test␊ 342 | ␊ 343 | [12:00:00] Finished 'main' after 100 ms`, 344 | } 345 | 346 | ## 'debug' option | stream-stream {"opts": {"debug": false}} 347 | 348 | > Snapshot 1 349 | 350 | { 351 | exitCode: 0, 352 | stderr: '', 353 | stdout: `[12:00:00] Starting 'main'...␊ 354 | test␊ 355 | ␊ 356 | [12:00:00] Finished 'main' after 100 ms`, 357 | } 358 | 359 | ## 'debug' option | stream-stream {"opts": {"debug": true}} 360 | 361 | > Snapshot 1 362 | 363 | { 364 | exitCode: 0, 365 | stderr: '', 366 | stdout: `[12:00:00] Starting 'main'...␊ 367 | [12:00:00] [gulp-execa] echo test␊ 368 | test␊ 369 | ␊ 370 | [12:00:00] Finished 'main' after 100 ms`, 371 | } 372 | 373 | ## 'debug' option | stream-stream {"opts": {"debug": false, "echo": false}} 374 | 375 | > Snapshot 1 376 | 377 | { 378 | exitCode: 0, 379 | stderr: '', 380 | stdout: `[12:00:00] Starting 'main'...␊ 381 | test␊ 382 | ␊ 383 | [12:00:00] Finished 'main' after 100 ms`, 384 | } 385 | 386 | ## 'debug' option | stream-stream {"opts": {"debug": true, "echo": false}} 387 | 388 | > Snapshot 1 389 | 390 | { 391 | exitCode: 0, 392 | stderr: '', 393 | stdout: `[12:00:00] Starting 'main'...␊ 394 | test␊ 395 | ␊ 396 | [12:00:00] Finished 'main' after 100 ms`, 397 | } 398 | 399 | ## 'debug' option | stream-stream {"opts": {"debug": false, "echo": true}} 400 | 401 | > Snapshot 1 402 | 403 | { 404 | exitCode: 0, 405 | stderr: '', 406 | stdout: `[12:00:00] Starting 'main'...␊ 407 | [12:00:00] [gulp-execa] echo test␊ 408 | test␊ 409 | ␊ 410 | [12:00:00] Finished 'main' after 100 ms`, 411 | } 412 | 413 | ## 'debug' option | stream-stream {"opts": {"debug": true, "echo": true}} 414 | 415 | > Snapshot 1 416 | 417 | { 418 | exitCode: 0, 419 | stderr: '', 420 | stdout: `[12:00:00] Starting 'main'...␊ 421 | [12:00:00] [gulp-execa] echo test␊ 422 | test␊ 423 | ␊ 424 | [12:00:00] Finished 'main' after 100 ms`, 425 | } 426 | 427 | ## 'debug' option | stream-stream {"opts": {"debug": true, "stderr": "pipe", "stdout": "pipe"}} 428 | 429 | > Snapshot 1 430 | 431 | { 432 | exitCode: 0, 433 | stderr: '', 434 | stdout: `[12:00:00] Starting 'main'...␊ 435 | [12:00:00] [gulp-execa] echo test␊ 436 | test␊ 437 | ␊ 438 | [12:00:00] Finished 'main' after 100 ms`, 439 | } 440 | 441 | ## 'debug' option | stream-stream {"opts": {"debug": true, "stdio": "pipe"}} 442 | 443 | > Snapshot 1 444 | 445 | { 446 | exitCode: 0, 447 | stderr: '', 448 | stdout: `[12:00:00] Starting 'main'...␊ 449 | [12:00:00] [gulp-execa] echo test␊ 450 | test␊ 451 | ␊ 452 | [12:00:00] Finished 'main' after 100 ms`, 453 | } 454 | 455 | ## 'debug' option | stream-stream {"opts": {"debug": true, "stderr": "pipe", "stdio": "pipe", "stdout": "pipe"}} 456 | 457 | > Snapshot 1 458 | 459 | { 460 | exitCode: 0, 461 | stderr: '', 462 | stdout: `[12:00:00] Starting 'main'...␊ 463 | [12:00:00] [gulp-execa] echo test␊ 464 | test␊ 465 | ␊ 466 | [12:00:00] Finished 'main' after 100 ms`, 467 | } 468 | 469 | ## 'debug' option | stream-save {"opts": {"debug": false}} 470 | 471 | > Snapshot 1 472 | 473 | { 474 | exitCode: 0, 475 | stderr: '', 476 | stdout: `[12:00:00] Starting 'main'...␊ 477 | [␊ 478 | {␊ 479 | "command": "echo test",␊ 480 | "escapedCommand": "echo test",␊ 481 | "cwd": /path␊ 482 | "durationMs": 1,␊ 483 | "failed": false,␊ 484 | "timedOut": false,␊ 485 | "isCanceled": false,␊ 486 | "isGracefullyCanceled": false,␊ 487 | "isTerminated": false,␊ 488 | "isMaxBuffer": false,␊ 489 | "isForcefullyTerminated": false,␊ 490 | "exitCode": 0,␊ 491 | "stdout": "test",␊ 492 | "stderr": "",␊ 493 | "stdio": [␊ 494 | null,␊ 495 | "test",␊ 496 | ""␊ 497 | ],␊ 498 | "ipcOutput": [],␊ 499 | "pipedFrom": []␊ 500 | }␊ 501 | ]␊ 502 | [12:00:00] Finished 'main' after 100 ms`, 503 | } 504 | 505 | ## 'debug' option | stream-save {"opts": {"debug": true}} 506 | 507 | > Snapshot 1 508 | 509 | { 510 | exitCode: 0, 511 | stderr: '', 512 | stdout: `[12:00:00] Starting 'main'...␊ 513 | [12:00:00] [gulp-execa] echo test␊ 514 | [␊ 515 | {␊ 516 | "command": "echo test",␊ 517 | "escapedCommand": "echo test",␊ 518 | "cwd": /path␊ 519 | "durationMs": 1,␊ 520 | "failed": false,␊ 521 | "timedOut": false,␊ 522 | "isCanceled": false,␊ 523 | "isGracefullyCanceled": false,␊ 524 | "isTerminated": false,␊ 525 | "isMaxBuffer": false,␊ 526 | "isForcefullyTerminated": false,␊ 527 | "exitCode": 0,␊ 528 | "stdout": "test",␊ 529 | "stderr": "",␊ 530 | "stdio": [␊ 531 | null,␊ 532 | "test",␊ 533 | ""␊ 534 | ],␊ 535 | "ipcOutput": [],␊ 536 | "pipedFrom": []␊ 537 | }␊ 538 | ]␊ 539 | [12:00:00] Finished 'main' after 100 ms`, 540 | } 541 | 542 | ## 'debug' option | stream-save {"opts": {"debug": false, "echo": false}} 543 | 544 | > Snapshot 1 545 | 546 | { 547 | exitCode: 0, 548 | stderr: '', 549 | stdout: `[12:00:00] Starting 'main'...␊ 550 | [␊ 551 | {␊ 552 | "command": "echo test",␊ 553 | "escapedCommand": "echo test",␊ 554 | "cwd": /path␊ 555 | "durationMs": 1,␊ 556 | "failed": false,␊ 557 | "timedOut": false,␊ 558 | "isCanceled": false,␊ 559 | "isGracefullyCanceled": false,␊ 560 | "isTerminated": false,␊ 561 | "isMaxBuffer": false,␊ 562 | "isForcefullyTerminated": false,␊ 563 | "exitCode": 0,␊ 564 | "stdout": "test",␊ 565 | "stderr": "",␊ 566 | "stdio": [␊ 567 | null,␊ 568 | "test",␊ 569 | ""␊ 570 | ],␊ 571 | "ipcOutput": [],␊ 572 | "pipedFrom": []␊ 573 | }␊ 574 | ]␊ 575 | [12:00:00] Finished 'main' after 100 ms`, 576 | } 577 | 578 | ## 'debug' option | stream-save {"opts": {"debug": true, "echo": false}} 579 | 580 | > Snapshot 1 581 | 582 | { 583 | exitCode: 0, 584 | stderr: '', 585 | stdout: `[12:00:00] Starting 'main'...␊ 586 | [␊ 587 | {␊ 588 | "command": "echo test",␊ 589 | "escapedCommand": "echo test",␊ 590 | "cwd": /path␊ 591 | "durationMs": 1,␊ 592 | "failed": false,␊ 593 | "timedOut": false,␊ 594 | "isCanceled": false,␊ 595 | "isGracefullyCanceled": false,␊ 596 | "isTerminated": false,␊ 597 | "isMaxBuffer": false,␊ 598 | "isForcefullyTerminated": false,␊ 599 | "exitCode": 0,␊ 600 | "stdout": "test",␊ 601 | "stderr": "",␊ 602 | "stdio": [␊ 603 | null,␊ 604 | "test",␊ 605 | ""␊ 606 | ],␊ 607 | "ipcOutput": [],␊ 608 | "pipedFrom": []␊ 609 | }␊ 610 | ]␊ 611 | [12:00:00] Finished 'main' after 100 ms`, 612 | } 613 | 614 | ## 'debug' option | stream-save {"opts": {"debug": false, "echo": true}} 615 | 616 | > Snapshot 1 617 | 618 | { 619 | exitCode: 0, 620 | stderr: '', 621 | stdout: `[12:00:00] Starting 'main'...␊ 622 | [12:00:00] [gulp-execa] echo test␊ 623 | [␊ 624 | {␊ 625 | "command": "echo test",␊ 626 | "escapedCommand": "echo test",␊ 627 | "cwd": /path␊ 628 | "durationMs": 1,␊ 629 | "failed": false,␊ 630 | "timedOut": false,␊ 631 | "isCanceled": false,␊ 632 | "isGracefullyCanceled": false,␊ 633 | "isTerminated": false,␊ 634 | "isMaxBuffer": false,␊ 635 | "isForcefullyTerminated": false,␊ 636 | "exitCode": 0,␊ 637 | "stdout": "test",␊ 638 | "stderr": "",␊ 639 | "stdio": [␊ 640 | null,␊ 641 | "test",␊ 642 | ""␊ 643 | ],␊ 644 | "ipcOutput": [],␊ 645 | "pipedFrom": []␊ 646 | }␊ 647 | ]␊ 648 | [12:00:00] Finished 'main' after 100 ms`, 649 | } 650 | 651 | ## 'debug' option | stream-save {"opts": {"debug": true, "echo": true}} 652 | 653 | > Snapshot 1 654 | 655 | { 656 | exitCode: 0, 657 | stderr: '', 658 | stdout: `[12:00:00] Starting 'main'...␊ 659 | [12:00:00] [gulp-execa] echo test␊ 660 | [␊ 661 | {␊ 662 | "command": "echo test",␊ 663 | "escapedCommand": "echo test",␊ 664 | "cwd": /path␊ 665 | "durationMs": 1,␊ 666 | "failed": false,␊ 667 | "timedOut": false,␊ 668 | "isCanceled": false,␊ 669 | "isGracefullyCanceled": false,␊ 670 | "isTerminated": false,␊ 671 | "isMaxBuffer": false,␊ 672 | "isForcefullyTerminated": false,␊ 673 | "exitCode": 0,␊ 674 | "stdout": "test",␊ 675 | "stderr": "",␊ 676 | "stdio": [␊ 677 | null,␊ 678 | "test",␊ 679 | ""␊ 680 | ],␊ 681 | "ipcOutput": [],␊ 682 | "pipedFrom": []␊ 683 | }␊ 684 | ]␊ 685 | [12:00:00] Finished 'main' after 100 ms`, 686 | } 687 | 688 | ## 'debug' option | stream-save {"opts": {"debug": true, "stderr": "pipe", "stdout": "pipe"}} 689 | 690 | > Snapshot 1 691 | 692 | { 693 | exitCode: 0, 694 | stderr: '', 695 | stdout: `[12:00:00] Starting 'main'...␊ 696 | [12:00:00] [gulp-execa] echo test␊ 697 | [␊ 698 | {␊ 699 | "command": "echo test",␊ 700 | "escapedCommand": "echo test",␊ 701 | "cwd": /path␊ 702 | "durationMs": 1,␊ 703 | "failed": false,␊ 704 | "timedOut": false,␊ 705 | "isCanceled": false,␊ 706 | "isGracefullyCanceled": false,␊ 707 | "isTerminated": false,␊ 708 | "isMaxBuffer": false,␊ 709 | "isForcefullyTerminated": false,␊ 710 | "exitCode": 0,␊ 711 | "stdout": "test",␊ 712 | "stderr": "",␊ 713 | "stdio": [␊ 714 | null,␊ 715 | "test",␊ 716 | ""␊ 717 | ],␊ 718 | "ipcOutput": [],␊ 719 | "pipedFrom": []␊ 720 | }␊ 721 | ]␊ 722 | [12:00:00] Finished 'main' after 100 ms`, 723 | } 724 | 725 | ## 'debug' option | stream-save {"opts": {"debug": true, "stdio": "pipe"}} 726 | 727 | > Snapshot 1 728 | 729 | { 730 | exitCode: 0, 731 | stderr: '', 732 | stdout: `[12:00:00] Starting 'main'...␊ 733 | [12:00:00] [gulp-execa] echo test␊ 734 | [␊ 735 | {␊ 736 | "command": "echo test",␊ 737 | "escapedCommand": "echo test",␊ 738 | "cwd": /path␊ 739 | "durationMs": 1,␊ 740 | "failed": false,␊ 741 | "timedOut": false,␊ 742 | "isCanceled": false,␊ 743 | "isGracefullyCanceled": false,␊ 744 | "isTerminated": false,␊ 745 | "isMaxBuffer": false,␊ 746 | "isForcefullyTerminated": false,␊ 747 | "exitCode": 0,␊ 748 | "stdout": "test",␊ 749 | "stderr": "",␊ 750 | "stdio": [␊ 751 | null,␊ 752 | "test",␊ 753 | ""␊ 754 | ],␊ 755 | "ipcOutput": [],␊ 756 | "pipedFrom": []␊ 757 | }␊ 758 | ]␊ 759 | [12:00:00] Finished 'main' after 100 ms`, 760 | } 761 | 762 | ## 'debug' option | stream-save {"opts": {"debug": true, "stderr": "pipe", "stdio": "pipe", "stdout": "pipe"}} 763 | 764 | > Snapshot 1 765 | 766 | { 767 | exitCode: 0, 768 | stderr: '', 769 | stdout: `[12:00:00] Starting 'main'...␊ 770 | [12:00:00] [gulp-execa] echo test␊ 771 | [␊ 772 | {␊ 773 | "command": "echo test",␊ 774 | "escapedCommand": "echo test",␊ 775 | "cwd": /path␊ 776 | "durationMs": 1,␊ 777 | "failed": false,␊ 778 | "timedOut": false,␊ 779 | "isCanceled": false,␊ 780 | "isGracefullyCanceled": false,␊ 781 | "isTerminated": false,␊ 782 | "isMaxBuffer": false,␊ 783 | "isForcefullyTerminated": false,␊ 784 | "exitCode": 0,␊ 785 | "stdout": "test",␊ 786 | "stderr": "",␊ 787 | "stdio": [␊ 788 | null,␊ 789 | "test",␊ 790 | ""␊ 791 | ],␊ 792 | "ipcOutput": [],␊ 793 | "pipedFrom": []␊ 794 | }␊ 795 | ]␊ 796 | [12:00:00] Finished 'main' after 100 ms`, 797 | } 798 | -------------------------------------------------------------------------------- /src/snapshots/build/src/options/debug.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/options/debug.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/options/main.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/options/main.test.js` 2 | 3 | The actual snapshot is saved in `main.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## Invalid options | exec {"opts": false} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 1, 13 | stderr: `Options must be a plain object: false␊ 14 | at STACK TRACE`, 15 | stdout: '[12:00:00] Starting \'main\'...', 16 | } 17 | 18 | ## Invalid options | exec {"opts": {"cwd": false}} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 1, 24 | stderr: `The "cwd" option must be a string or a file URL: false.␊ 25 | at STACK TRACE`, 26 | stdout: `[12:00:00] Starting 'main'...␊ 27 | [12:00:00] [gulp-execa] echo test`, 28 | } 29 | 30 | ## Invalid options | exec {"opts": {"echo": 0}} 31 | 32 | > Snapshot 1 33 | 34 | { 35 | exitCode: 1, 36 | stderr: `Option "echo" must be of type:␊ 37 | boolean␊ 38 | but instead received:␊ 39 | number␊ 40 | ␊ 41 | Example:␊ 42 | {␊ 43 | "echo": true␊ 44 | }`, 45 | stdout: '[12:00:00] Starting \'main\'...', 46 | } 47 | 48 | ## Invalid options | exec {"opts": {"debug": 0}} 49 | 50 | > Snapshot 1 51 | 52 | { 53 | exitCode: 1, 54 | stderr: `Option "debug" must be of type:␊ 55 | boolean␊ 56 | but instead received:␊ 57 | number␊ 58 | ␊ 59 | Example:␊ 60 | {␊ 61 | "debug": true␊ 62 | }`, 63 | stdout: '[12:00:00] Starting \'main\'...', 64 | } 65 | 66 | ## Invalid options | exec {"opts": {"result": "invalid"}} 67 | 68 | > Snapshot 1 69 | 70 | { 71 | exitCode: 1, 72 | stderr: `Option 'result' 'invalid' must be one of: save, replace␊ 73 | at STACK TRACE`, 74 | stdout: '[12:00:00] Starting \'main\'...', 75 | } 76 | 77 | ## Invalid options | exec {"opts": {"from": "invalid"}} 78 | 79 | > Snapshot 1 80 | 81 | { 82 | exitCode: 1, 83 | stderr: `Option 'from' 'invalid' must be one of: stdout, stderr, all␊ 84 | at STACK TRACE`, 85 | stdout: '[12:00:00] Starting \'main\'...', 86 | } 87 | 88 | ## Invalid options | task {"opts": false} 89 | 90 | > Snapshot 1 91 | 92 | { 93 | exitCode: 1, 94 | stderr: `Options must be a plain object: false␊ 95 | at STACK TRACE`, 96 | stdout: '', 97 | } 98 | 99 | ## Invalid options | task {"opts": {"cwd": false}} 100 | 101 | > Snapshot 1 102 | 103 | { 104 | exitCode: 1, 105 | stderr: `The "cwd" option must be a string or a file URL: false.␊ 106 | at STACK TRACE`, 107 | stdout: `[12:00:00] Starting 'main'...␊ 108 | [12:00:00] [gulp-execa] echo test`, 109 | } 110 | 111 | ## Invalid options | task {"opts": {"echo": 0}} 112 | 113 | > Snapshot 1 114 | 115 | { 116 | exitCode: 1, 117 | stderr: `Option "echo" must be of type:␊ 118 | boolean␊ 119 | but instead received:␊ 120 | number␊ 121 | ␊ 122 | Example:␊ 123 | {␊ 124 | "echo": true␊ 125 | }␊ 126 | ]`, 127 | stdout: '', 128 | } 129 | 130 | ## Invalid options | task {"opts": {"debug": 0}} 131 | 132 | > Snapshot 1 133 | 134 | { 135 | exitCode: 1, 136 | stderr: `Option "debug" must be of type:␊ 137 | boolean␊ 138 | but instead received:␊ 139 | number␊ 140 | ␊ 141 | Example:␊ 142 | {␊ 143 | "debug": true␊ 144 | }␊ 145 | ]`, 146 | stdout: '', 147 | } 148 | 149 | ## Invalid options | task {"opts": {"result": "invalid"}} 150 | 151 | > Snapshot 1 152 | 153 | { 154 | exitCode: 1, 155 | stderr: `Option 'result' 'invalid' must be one of: save, replace␊ 156 | at STACK TRACE`, 157 | stdout: '', 158 | } 159 | 160 | ## Invalid options | task {"opts": {"from": "invalid"}} 161 | 162 | > Snapshot 1 163 | 164 | { 165 | exitCode: 1, 166 | stderr: `Option 'from' 'invalid' must be one of: stdout, stderr, all␊ 167 | at STACK TRACE`, 168 | stdout: '', 169 | } 170 | 171 | ## Invalid options | stream-buffer {"opts": false} 172 | 173 | > Snapshot 1 174 | 175 | { 176 | exitCode: 1, 177 | stderr: `Options must be a plain object: false␊ 178 | at STACK TRACE`, 179 | stdout: '[12:00:00] Starting \'main\'...', 180 | } 181 | 182 | ## Invalid options | stream-buffer {"opts": {"cwd": false}} 183 | 184 | > Snapshot 1 185 | 186 | { 187 | exitCode: 1, 188 | stderr: `The "cwd" option must be a string or a file URL: false.␊ 189 | at STACK TRACE`, 190 | stdout: '[12:00:00] Starting \'main\'...', 191 | } 192 | 193 | ## Invalid options | stream-buffer {"opts": {"echo": 0}} 194 | 195 | > Snapshot 1 196 | 197 | { 198 | exitCode: 1, 199 | stderr: `Option "echo" must be of type:␊ 200 | boolean␊ 201 | but instead received:␊ 202 | number␊ 203 | ␊ 204 | Example:␊ 205 | {␊ 206 | "echo": true␊ 207 | }`, 208 | stdout: '[12:00:00] Starting \'main\'...', 209 | } 210 | 211 | ## Invalid options | stream-buffer {"opts": {"debug": 0}} 212 | 213 | > Snapshot 1 214 | 215 | { 216 | exitCode: 1, 217 | stderr: `Option "debug" must be of type:␊ 218 | boolean␊ 219 | but instead received:␊ 220 | number␊ 221 | ␊ 222 | Example:␊ 223 | {␊ 224 | "debug": false␊ 225 | }`, 226 | stdout: '[12:00:00] Starting \'main\'...', 227 | } 228 | 229 | ## Invalid options | stream-buffer {"opts": {"result": "invalid"}} 230 | 231 | > Snapshot 1 232 | 233 | { 234 | exitCode: 1, 235 | stderr: `Option 'result' 'invalid' must be one of: save, replace␊ 236 | at STACK TRACE`, 237 | stdout: '[12:00:00] Starting \'main\'...', 238 | } 239 | 240 | ## Invalid options | stream-buffer {"opts": {"from": "invalid"}} 241 | 242 | > Snapshot 1 243 | 244 | { 245 | exitCode: 1, 246 | stderr: `Option 'from' 'invalid' must be one of: stdout, stderr, all␊ 247 | at STACK TRACE`, 248 | stdout: '[12:00:00] Starting \'main\'...', 249 | } 250 | 251 | ## Invalid options | stream-stream {"opts": false} 252 | 253 | > Snapshot 1 254 | 255 | { 256 | exitCode: 1, 257 | stderr: `Options must be a plain object: false␊ 258 | at STACK TRACE`, 259 | stdout: '[12:00:00] Starting \'main\'...', 260 | } 261 | 262 | ## Invalid options | stream-stream {"opts": {"cwd": false}} 263 | 264 | > Snapshot 1 265 | 266 | { 267 | exitCode: 1, 268 | stderr: `The "cwd" option must be a string or a file URL: false.␊ 269 | at STACK TRACE`, 270 | stdout: '[12:00:00] Starting \'main\'...', 271 | } 272 | 273 | ## Invalid options | stream-stream {"opts": {"echo": 0}} 274 | 275 | > Snapshot 1 276 | 277 | { 278 | exitCode: 1, 279 | stderr: `Option "echo" must be of type:␊ 280 | boolean␊ 281 | but instead received:␊ 282 | number␊ 283 | ␊ 284 | Example:␊ 285 | {␊ 286 | "echo": true␊ 287 | }`, 288 | stdout: '[12:00:00] Starting \'main\'...', 289 | } 290 | 291 | ## Invalid options | stream-stream {"opts": {"debug": 0}} 292 | 293 | > Snapshot 1 294 | 295 | { 296 | exitCode: 1, 297 | stderr: `Option "debug" must be of type:␊ 298 | boolean␊ 299 | but instead received:␊ 300 | number␊ 301 | ␊ 302 | Example:␊ 303 | {␊ 304 | "debug": false␊ 305 | }`, 306 | stdout: '[12:00:00] Starting \'main\'...', 307 | } 308 | 309 | ## Invalid options | stream-stream {"opts": {"result": "invalid"}} 310 | 311 | > Snapshot 1 312 | 313 | { 314 | exitCode: 1, 315 | stderr: `Option 'result' 'invalid' must be one of: save, replace␊ 316 | at STACK TRACE`, 317 | stdout: '[12:00:00] Starting \'main\'...', 318 | } 319 | 320 | ## Invalid options | stream-stream {"opts": {"from": "invalid"}} 321 | 322 | > Snapshot 1 323 | 324 | { 325 | exitCode: 1, 326 | stderr: `Option 'from' 'invalid' must be one of: stdout, stderr, all␊ 327 | at STACK TRACE`, 328 | stdout: '[12:00:00] Starting \'main\'...', 329 | } 330 | 331 | ## Invalid options | stream-save {"opts": false} 332 | 333 | > Snapshot 1 334 | 335 | { 336 | exitCode: 1, 337 | stderr: `Options must be a plain object: false␊ 338 | at STACK TRACE`, 339 | stdout: '[12:00:00] Starting \'main\'...', 340 | } 341 | 342 | ## Invalid options | stream-save {"opts": {"cwd": false}} 343 | 344 | > Snapshot 1 345 | 346 | { 347 | exitCode: 1, 348 | stderr: `The "cwd" option must be a string or a file URL: false.␊ 349 | at STACK TRACE`, 350 | stdout: '[12:00:00] Starting \'main\'...', 351 | } 352 | 353 | ## Invalid options | stream-save {"opts": {"echo": 0}} 354 | 355 | > Snapshot 1 356 | 357 | { 358 | exitCode: 1, 359 | stderr: `Option "echo" must be of type:␊ 360 | boolean␊ 361 | but instead received:␊ 362 | number␊ 363 | ␊ 364 | Example:␊ 365 | {␊ 366 | "echo": true␊ 367 | }`, 368 | stdout: '[12:00:00] Starting \'main\'...', 369 | } 370 | 371 | ## Invalid options | stream-save {"opts": {"debug": 0}} 372 | 373 | > Snapshot 1 374 | 375 | { 376 | exitCode: 1, 377 | stderr: `Option "debug" must be of type:␊ 378 | boolean␊ 379 | but instead received:␊ 380 | number␊ 381 | ␊ 382 | Example:␊ 383 | {␊ 384 | "debug": false␊ 385 | }`, 386 | stdout: '[12:00:00] Starting \'main\'...', 387 | } 388 | 389 | ## Invalid options | stream-save {"opts": {"result": "invalid"}} 390 | 391 | > Snapshot 1 392 | 393 | { 394 | exitCode: 1, 395 | stderr: `Option 'result' 'invalid' must be one of: save, replace␊ 396 | at STACK TRACE`, 397 | stdout: '[12:00:00] Starting \'main\'...', 398 | } 399 | 400 | ## Invalid options | stream-save {"opts": {"from": "invalid"}} 401 | 402 | > Snapshot 1 403 | 404 | { 405 | exitCode: 1, 406 | stderr: `Option 'from' 'invalid' must be one of: stdout, stderr, all␊ 407 | at STACK TRACE`, 408 | stdout: '[12:00:00] Starting \'main\'...', 409 | } 410 | 411 | ## Valid options | {"opts": {"env": [Object]}} (0) exec 412 | 413 | > Snapshot 1 414 | 415 | { 416 | exitCode: 0, 417 | stderr: '', 418 | stdout: `[12:00:00] Starting 'main'...␊ 419 | [12:00:00] [gulp-execa] echo test␊ 420 | test␊ 421 | [12:00:00] Finished 'main' after 100 ms`, 422 | } 423 | 424 | ## Valid options | {"opts": {"env": [Object]}} (0) task 425 | 426 | > Snapshot 1 427 | 428 | { 429 | exitCode: 0, 430 | stderr: '', 431 | stdout: `[12:00:00] Starting 'main'...␊ 432 | [12:00:00] [gulp-execa] echo test␊ 433 | test␊ 434 | [12:00:00] Finished 'main' after 100 ms`, 435 | } 436 | 437 | ## Valid options | {"opts": {"env": [Object]}} (0) stream-buffer 438 | 439 | > Snapshot 1 440 | 441 | { 442 | exitCode: 0, 443 | stderr: '', 444 | stdout: `[12:00:00] Starting 'main'...␊ 445 | test␊ 446 | ␊ 447 | [12:00:00] Finished 'main' after 100 ms`, 448 | } 449 | 450 | ## Valid options | {"opts": {"env": [Object]}} (0) stream-stream 451 | 452 | > Snapshot 1 453 | 454 | { 455 | exitCode: 0, 456 | stderr: '', 457 | stdout: `[12:00:00] Starting 'main'...␊ 458 | test␊ 459 | ␊ 460 | [12:00:00] Finished 'main' after 100 ms`, 461 | } 462 | 463 | ## Valid options | {"opts": {"env": [Object]}} (0) stream-save 464 | 465 | > Snapshot 1 466 | 467 | { 468 | exitCode: 0, 469 | stderr: '', 470 | stdout: `[12:00:00] Starting 'main'...␊ 471 | [␊ 472 | {␊ 473 | "command": "echo test",␊ 474 | "escapedCommand": "echo test",␊ 475 | "cwd": /path␊ 476 | "durationMs": 1,␊ 477 | "failed": false,␊ 478 | "timedOut": false,␊ 479 | "isCanceled": false,␊ 480 | "isGracefullyCanceled": false,␊ 481 | "isTerminated": false,␊ 482 | "isMaxBuffer": false,␊ 483 | "isForcefullyTerminated": false,␊ 484 | "exitCode": 0,␊ 485 | "stdout": "test",␊ 486 | "stderr": "",␊ 487 | "stdio": [␊ 488 | null,␊ 489 | "test",␊ 490 | ""␊ 491 | ],␊ 492 | "ipcOutput": [],␊ 493 | "pipedFrom": []␊ 494 | }␊ 495 | ]␊ 496 | [12:00:00] Finished 'main' after 100 ms`, 497 | } 498 | 499 | ## Valid options | {"opts": {"env": [Object]}} (1) exec 500 | 501 | > Snapshot 1 502 | 503 | { 504 | exitCode: 0, 505 | stderr: '', 506 | stdout: `[12:00:00] Starting 'main'...␊ 507 | [12:00:00] [gulp-execa] echo test␊ 508 | test␊ 509 | [12:00:00] Finished 'main' after 100 ms`, 510 | } 511 | 512 | ## Valid options | {"opts": {"env": [Object]}} (1) task 513 | 514 | > Snapshot 1 515 | 516 | { 517 | exitCode: 0, 518 | stderr: '', 519 | stdout: `[12:00:00] Starting 'main'...␊ 520 | [12:00:00] [gulp-execa] echo test␊ 521 | test␊ 522 | [12:00:00] Finished 'main' after 100 ms`, 523 | } 524 | 525 | ## Valid options | {"opts": {"env": [Object]}} (1) stream-buffer 526 | 527 | > Snapshot 1 528 | 529 | { 530 | exitCode: 0, 531 | stderr: '', 532 | stdout: `[12:00:00] Starting 'main'...␊ 533 | test␊ 534 | ␊ 535 | [12:00:00] Finished 'main' after 100 ms`, 536 | } 537 | 538 | ## Valid options | {"opts": {"env": [Object]}} (1) stream-stream 539 | 540 | > Snapshot 1 541 | 542 | { 543 | exitCode: 0, 544 | stderr: '', 545 | stdout: `[12:00:00] Starting 'main'...␊ 546 | test␊ 547 | ␊ 548 | [12:00:00] Finished 'main' after 100 ms`, 549 | } 550 | 551 | ## Valid options | {"opts": {"env": [Object]}} (1) stream-save 552 | 553 | > Snapshot 1 554 | 555 | { 556 | exitCode: 0, 557 | stderr: '', 558 | stdout: `[12:00:00] Starting 'main'...␊ 559 | [␊ 560 | {␊ 561 | "command": "echo test",␊ 562 | "escapedCommand": "echo test",␊ 563 | "cwd": /path␊ 564 | "durationMs": 1,␊ 565 | "failed": false,␊ 566 | "timedOut": false,␊ 567 | "isCanceled": false,␊ 568 | "isGracefullyCanceled": false,␊ 569 | "isTerminated": false,␊ 570 | "isMaxBuffer": false,␊ 571 | "isForcefullyTerminated": false,␊ 572 | "exitCode": 0,␊ 573 | "stdout": "test",␊ 574 | "stderr": "",␊ 575 | "stdio": [␊ 576 | null,␊ 577 | "test",␊ 578 | ""␊ 579 | ],␊ 580 | "ipcOutput": [],␊ 581 | "pipedFrom": []␊ 582 | }␊ 583 | ]␊ 584 | [12:00:00] Finished 'main' after 100 ms`, 585 | } 586 | 587 | ## No options | exec {} 588 | 589 | > Snapshot 1 590 | 591 | { 592 | exitCode: 0, 593 | stderr: '', 594 | stdout: `[12:00:00] Starting 'main'...␊ 595 | [12:00:00] [gulp-execa] echo test␊ 596 | test␊ 597 | [12:00:00] Finished 'main' after 100 ms`, 598 | } 599 | 600 | ## No options | exec {"opts": {}} 601 | 602 | > Snapshot 1 603 | 604 | { 605 | exitCode: 0, 606 | stderr: '', 607 | stdout: `[12:00:00] Starting 'main'...␊ 608 | [12:00:00] [gulp-execa] echo test␊ 609 | test␊ 610 | [12:00:00] Finished 'main' after 100 ms`, 611 | } 612 | 613 | ## No options | task {} 614 | 615 | > Snapshot 1 616 | 617 | { 618 | exitCode: 0, 619 | stderr: '', 620 | stdout: `[12:00:00] Starting 'main'...␊ 621 | [12:00:00] [gulp-execa] echo test␊ 622 | test␊ 623 | [12:00:00] Finished 'main' after 100 ms`, 624 | } 625 | 626 | ## No options | task {"opts": {}} 627 | 628 | > Snapshot 1 629 | 630 | { 631 | exitCode: 0, 632 | stderr: '', 633 | stdout: `[12:00:00] Starting 'main'...␊ 634 | [12:00:00] [gulp-execa] echo test␊ 635 | test␊ 636 | [12:00:00] Finished 'main' after 100 ms`, 637 | } 638 | 639 | ## No options | stream-buffer {} 640 | 641 | > Snapshot 1 642 | 643 | { 644 | exitCode: 0, 645 | stderr: '', 646 | stdout: `[12:00:00] Starting 'main'...␊ 647 | test␊ 648 | ␊ 649 | [12:00:00] Finished 'main' after 100 ms`, 650 | } 651 | 652 | ## No options | stream-buffer {"opts": {}} 653 | 654 | > Snapshot 1 655 | 656 | { 657 | exitCode: 0, 658 | stderr: '', 659 | stdout: `[12:00:00] Starting 'main'...␊ 660 | test␊ 661 | ␊ 662 | [12:00:00] Finished 'main' after 100 ms`, 663 | } 664 | 665 | ## No options | stream-stream {} 666 | 667 | > Snapshot 1 668 | 669 | { 670 | exitCode: 0, 671 | stderr: '', 672 | stdout: `[12:00:00] Starting 'main'...␊ 673 | test␊ 674 | ␊ 675 | [12:00:00] Finished 'main' after 100 ms`, 676 | } 677 | 678 | ## No options | stream-stream {"opts": {}} 679 | 680 | > Snapshot 1 681 | 682 | { 683 | exitCode: 0, 684 | stderr: '', 685 | stdout: `[12:00:00] Starting 'main'...␊ 686 | test␊ 687 | ␊ 688 | [12:00:00] Finished 'main' after 100 ms`, 689 | } 690 | 691 | ## No options | stream-save {} 692 | 693 | > Snapshot 1 694 | 695 | { 696 | exitCode: 0, 697 | stderr: '', 698 | stdout: `[12:00:00] Starting 'main'...␊ 699 | [␊ 700 | {␊ 701 | "command": "echo test",␊ 702 | "escapedCommand": "echo test",␊ 703 | "cwd": /path␊ 704 | "durationMs": 1,␊ 705 | "failed": false,␊ 706 | "timedOut": false,␊ 707 | "isCanceled": false,␊ 708 | "isGracefullyCanceled": false,␊ 709 | "isTerminated": false,␊ 710 | "isMaxBuffer": false,␊ 711 | "isForcefullyTerminated": false,␊ 712 | "exitCode": 0,␊ 713 | "stdout": "test",␊ 714 | "stderr": "",␊ 715 | "stdio": [␊ 716 | null,␊ 717 | "test",␊ 718 | ""␊ 719 | ],␊ 720 | "ipcOutput": [],␊ 721 | "pipedFrom": []␊ 722 | }␊ 723 | ]␊ 724 | [12:00:00] Finished 'main' after 100 ms`, 725 | } 726 | 727 | ## No options | stream-save {"opts": {}} 728 | 729 | > Snapshot 1 730 | 731 | { 732 | exitCode: 0, 733 | stderr: '', 734 | stdout: `[12:00:00] Starting 'main'...␊ 735 | [␊ 736 | {␊ 737 | "command": "echo test",␊ 738 | "escapedCommand": "echo test",␊ 739 | "cwd": /path␊ 740 | "durationMs": 1,␊ 741 | "failed": false,␊ 742 | "timedOut": false,␊ 743 | "isCanceled": false,␊ 744 | "isGracefullyCanceled": false,␊ 745 | "isTerminated": false,␊ 746 | "isMaxBuffer": false,␊ 747 | "isForcefullyTerminated": false,␊ 748 | "exitCode": 0,␊ 749 | "stdout": "test",␊ 750 | "stderr": "",␊ 751 | "stdio": [␊ 752 | null,␊ 753 | "test",␊ 754 | ""␊ 755 | ],␊ 756 | "ipcOutput": [],␊ 757 | "pipedFrom": []␊ 758 | }␊ 759 | ]␊ 760 | [12:00:00] Finished 'main' after 100 ms`, 761 | } 762 | 763 | ## Default options | exec {"command": "gulp --version", "opts": {"env": [Object]}} 764 | 765 | > Snapshot 1 766 | 767 | { 768 | exitCode: 0, 769 | stderr: '', 770 | stdout: `[12:00:00] Starting 'main'...␊ 771 | [12:00:00] [gulp-execa] gulp --version␊ 772 | CLI version: 1.0.0␊ 773 | Local version: 1.0.0␊ 774 | [12:00:00] Finished 'main' after 100 ms`, 775 | } 776 | 777 | ## Default options | task {"command": "gulp --version", "opts": {"env": [Object]}} 778 | 779 | > Snapshot 1 780 | 781 | { 782 | exitCode: 0, 783 | stderr: '', 784 | stdout: `[12:00:00] Starting 'main'...␊ 785 | [12:00:00] [gulp-execa] gulp --version␊ 786 | CLI version: 1.0.0␊ 787 | Local version: 1.0.0␊ 788 | [12:00:00] Finished 'main' after 100 ms`, 789 | } 790 | 791 | ## Default options | stream-buffer {"command": "gulp --version", "opts": {"env": [Object]}} 792 | 793 | > Snapshot 1 794 | 795 | { 796 | exitCode: 0, 797 | stderr: '', 798 | stdout: `[12:00:00] Starting 'main'...␊ 799 | CLI version: 1.0.0␊ 800 | Local version: 1.0.0␊ 801 | ␊ 802 | [12:00:00] Finished 'main' after 100 ms`, 803 | } 804 | 805 | ## Default options | stream-stream {"command": "gulp --version", "opts": {"env": [Object]}} 806 | 807 | > Snapshot 1 808 | 809 | { 810 | exitCode: 0, 811 | stderr: '', 812 | stdout: `[12:00:00] Starting 'main'...␊ 813 | CLI version: 1.0.0␊ 814 | Local version: 1.0.0␊ 815 | ␊ 816 | [12:00:00] Finished 'main' after 100 ms`, 817 | } 818 | 819 | ## Default options | stream-save {"command": "gulp --version", "opts": {"env": [Object]}} 820 | 821 | > Snapshot 1 822 | 823 | { 824 | exitCode: 0, 825 | stderr: '', 826 | stdout: `[12:00:00] Starting 'main'...␊ 827 | [␊ 828 | {␊ 829 | "command": "gulp --version",␊ 830 | "escapedCommand": "gulp --version",␊ 831 | "cwd": /path␊ 832 | "durationMs": 1,␊ 833 | "failed": false,␊ 834 | "timedOut": false,␊ 835 | "isCanceled": false,␊ 836 | "isGracefullyCanceled": false,␊ 837 | "isTerminated": false,␊ 838 | "isMaxBuffer": false,␊ 839 | "isForcefullyTerminated": false,␊ 840 | "exitCode": 0,␊ 841 | "stdout": "CLI version: 1.0.0\\nLocal version: 1.0.0",␊ 842 | "stderr": "",␊ 843 | "stdio": [␊ 844 | null,␊ 845 | "CLI version: 1.0.0\\nLocal version: 1.0.0",␊ 846 | ""␊ 847 | ],␊ 848 | "ipcOutput": [],␊ 849 | "pipedFrom": []␊ 850 | }␊ 851 | ]␊ 852 | [12:00:00] Finished 'main' after 100 ms`, 853 | } 854 | -------------------------------------------------------------------------------- /src/snapshots/build/src/options/main.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/options/main.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/stream.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `src/stream.test.js` 2 | 3 | The actual snapshot is saved in `stream.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## stream() | stream-buffer {"task": "inputNotFunc"} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 1, 13 | stderr: `Option 'getInput' must be a function: echo test␊ 14 | at STACK TRACE`, 15 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 16 | } 17 | 18 | ## stream() | stream-buffer {"task": "inputThrows"} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 1, 24 | stderr: `error␊ 25 | at STACK TRACE`, 26 | stdout: '[12:00:00] Starting \'inputThrows\'...', 27 | } 28 | 29 | ## stream() | stream-buffer {"task": "inputThrowsAsync"} 30 | 31 | > Snapshot 1 32 | 33 | { 34 | exitCode: 1, 35 | stderr: `error␊ 36 | at STACK TRACE`, 37 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 38 | } 39 | 40 | ## stream() | stream-buffer {"task": "inputAsync"} 41 | 42 | > Snapshot 1 43 | 44 | { 45 | exitCode: 0, 46 | stderr: '', 47 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 48 | test␊ 49 | ␊ 50 | [12:00:00] Finished 'inputAsync' after 100 ms`, 51 | } 52 | 53 | ## stream() | stream-buffer {"command": "echo", "task": "inputFile"} 54 | 55 | > Snapshot 1 56 | 57 | { 58 | exitCode: 0, 59 | stderr: '', 60 | stdout: `[12:00:00] Starting 'inputFile'...␊ 61 | dummy.txt␊ 62 | ␊ 63 | [12:00:00] Finished 'inputFile' after 100 ms`, 64 | } 65 | 66 | ## stream() | stream-buffer {"task": "inputUndefined"} 67 | 68 | > Snapshot 1 69 | 70 | { 71 | exitCode: 0, 72 | stderr: '', 73 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 74 | one␊ 75 | ␊ 76 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 77 | } 78 | 79 | ## stream() | stream-buffer {"task": "severalFiles"} 80 | 81 | > Snapshot 1 82 | 83 | { 84 | exitCode: 0, 85 | stderr: '', 86 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 87 | test␊ 88 | ␊ 89 | test␊ 90 | ␊ 91 | [12:00:00] Finished 'severalFiles' after 100 ms`, 92 | } 93 | 94 | ## stream() | stream-buffer {"task": "severalTimes"} 95 | 96 | > Snapshot 1 97 | 98 | { 99 | exitCode: 0, 100 | stderr: '', 101 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 102 | test␊ 103 | ␊ 104 | [12:00:00] Finished 'severalTimes' after 100 ms`, 105 | } 106 | 107 | ## stream() | stream-buffer {} 108 | 109 | > Snapshot 1 110 | 111 | { 112 | exitCode: 0, 113 | stderr: '', 114 | stdout: `[12:00:00] Starting 'main'...␊ 115 | test␊ 116 | ␊ 117 | [12:00:00] Finished 'main' after 100 ms`, 118 | } 119 | 120 | ## stream() | stream-buffer {"command": {"command": "echo test", "stripFinalNewline": true}} 121 | 122 | > Snapshot 1 123 | 124 | { 125 | exitCode: 0, 126 | stderr: '', 127 | stdout: `[12:00:00] Starting 'main'...␊ 128 | test␊ 129 | [12:00:00] Finished 'main' after 100 ms`, 130 | } 131 | 132 | ## stream() | stream-buffer {"opts": {"encoding": "utf8"}} 133 | 134 | > Snapshot 1 135 | 136 | { 137 | exitCode: 0, 138 | stderr: '', 139 | stdout: `[12:00:00] Starting 'main'...␊ 140 | test␊ 141 | ␊ 142 | [12:00:00] Finished 'main' after 100 ms`, 143 | } 144 | 145 | ## stream() | stream-buffer {"opts": {"stripFinalNewline": true}} 146 | 147 | > Snapshot 1 148 | 149 | { 150 | exitCode: 0, 151 | stderr: '', 152 | stdout: `[12:00:00] Starting 'main'...␊ 153 | test␊ 154 | [12:00:00] Finished 'main' after 100 ms`, 155 | } 156 | 157 | ## stream() | stream-stream {"task": "inputNotFunc"} 158 | 159 | > Snapshot 1 160 | 161 | { 162 | exitCode: 1, 163 | stderr: `Option 'getInput' must be a function: echo test␊ 164 | at STACK TRACE`, 165 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 166 | } 167 | 168 | ## stream() | stream-stream {"task": "inputThrows"} 169 | 170 | > Snapshot 1 171 | 172 | { 173 | exitCode: 1, 174 | stderr: `error␊ 175 | at STACK TRACE`, 176 | stdout: '[12:00:00] Starting \'inputThrows\'...', 177 | } 178 | 179 | ## stream() | stream-stream {"task": "inputThrowsAsync"} 180 | 181 | > Snapshot 1 182 | 183 | { 184 | exitCode: 1, 185 | stderr: `error␊ 186 | at STACK TRACE`, 187 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 188 | } 189 | 190 | ## stream() | stream-stream {"task": "inputAsync"} 191 | 192 | > Snapshot 1 193 | 194 | { 195 | exitCode: 0, 196 | stderr: '', 197 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 198 | test␊ 199 | ␊ 200 | [12:00:00] Finished 'inputAsync' after 100 ms`, 201 | } 202 | 203 | ## stream() | stream-stream {"command": "echo", "task": "inputFile"} 204 | 205 | > Snapshot 1 206 | 207 | { 208 | exitCode: 0, 209 | stderr: '', 210 | stdout: `[12:00:00] Starting 'inputFile'...␊ 211 | dummy.txt␊ 212 | ␊ 213 | [12:00:00] Finished 'inputFile' after 100 ms`, 214 | } 215 | 216 | ## stream() | stream-stream {"task": "inputUndefined"} 217 | 218 | > Snapshot 1 219 | 220 | { 221 | exitCode: 0, 222 | stderr: '', 223 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 224 | one␊ 225 | ␊ 226 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 227 | } 228 | 229 | ## stream() | stream-stream {"task": "severalFiles"} 230 | 231 | > Snapshot 1 232 | 233 | { 234 | exitCode: 0, 235 | stderr: '', 236 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 237 | test␊ 238 | ␊ 239 | test␊ 240 | ␊ 241 | [12:00:00] Finished 'severalFiles' after 100 ms`, 242 | } 243 | 244 | ## stream() | stream-stream {"task": "severalTimes"} 245 | 246 | > Snapshot 1 247 | 248 | { 249 | exitCode: 0, 250 | stderr: '', 251 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 252 | test␊ 253 | ␊ 254 | [12:00:00] Finished 'severalTimes' after 100 ms`, 255 | } 256 | 257 | ## stream() | stream-stream {} 258 | 259 | > Snapshot 1 260 | 261 | { 262 | exitCode: 0, 263 | stderr: '', 264 | stdout: `[12:00:00] Starting 'main'...␊ 265 | test␊ 266 | ␊ 267 | [12:00:00] Finished 'main' after 100 ms`, 268 | } 269 | 270 | ## stream() | stream-stream {"command": {"command": "echo test", "stripFinalNewline": true}} 271 | 272 | > Snapshot 1 273 | 274 | { 275 | exitCode: 0, 276 | stderr: '', 277 | stdout: `[12:00:00] Starting 'main'...␊ 278 | test␊ 279 | ␊ 280 | [12:00:00] Finished 'main' after 100 ms`, 281 | } 282 | 283 | ## stream() | stream-stream {"opts": {"encoding": "utf8"}} 284 | 285 | > Snapshot 1 286 | 287 | { 288 | exitCode: 0, 289 | stderr: '', 290 | stdout: `[12:00:00] Starting 'main'...␊ 291 | test␊ 292 | ␊ 293 | [12:00:00] Finished 'main' after 100 ms`, 294 | } 295 | 296 | ## stream() | stream-stream {"opts": {"stripFinalNewline": true}} 297 | 298 | > Snapshot 1 299 | 300 | { 301 | exitCode: 0, 302 | stderr: '', 303 | stdout: `[12:00:00] Starting 'main'...␊ 304 | test␊ 305 | ␊ 306 | [12:00:00] Finished 'main' after 100 ms`, 307 | } 308 | 309 | ## stream() | stream-save {"task": "inputNotFunc"} 310 | 311 | > Snapshot 1 312 | 313 | { 314 | exitCode: 1, 315 | stderr: `Option 'getInput' must be a function: echo test␊ 316 | at STACK TRACE`, 317 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 318 | } 319 | 320 | ## stream() | stream-save {"task": "inputThrows"} 321 | 322 | > Snapshot 1 323 | 324 | { 325 | exitCode: 1, 326 | stderr: `error␊ 327 | at STACK TRACE`, 328 | stdout: '[12:00:00] Starting \'inputThrows\'...', 329 | } 330 | 331 | ## stream() | stream-save {"task": "inputThrowsAsync"} 332 | 333 | > Snapshot 1 334 | 335 | { 336 | exitCode: 1, 337 | stderr: `error␊ 338 | at STACK TRACE`, 339 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 340 | } 341 | 342 | ## stream() | stream-save {"task": "inputAsync"} 343 | 344 | > Snapshot 1 345 | 346 | { 347 | exitCode: 0, 348 | stderr: '', 349 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 350 | [␊ 351 | {␊ 352 | "command": "echo test",␊ 353 | "escapedCommand": "echo test",␊ 354 | "exitCode": 0,␊ 355 | "stdout": "test",␊ 356 | "stderr": "",␊ 357 | "failed": false,␊ 358 | "timedOut": false,␊ 359 | "isCanceled": false,␊ 360 | "killed": false␊ 361 | }␊ 362 | ]␊ 363 | [12:00:00] Finished 'inputAsync' after 100 ms`, 364 | } 365 | 366 | ## stream() | stream-save {"command": "echo", "task": "inputFile"} 367 | 368 | > Snapshot 1 369 | 370 | { 371 | exitCode: 0, 372 | stderr: '', 373 | stdout: `[12:00:00] Starting 'inputFile'...␊ 374 | [␊ 375 | {␊ 376 | "command": "echo dummy.txt",␊ 377 | "escapedCommand": "echo dummy.txt",␊ 378 | "exitCode": 0,␊ 379 | "stdout": "dummy.txt",␊ 380 | "stderr": "",␊ 381 | "failed": false,␊ 382 | "timedOut": false,␊ 383 | "isCanceled": false,␊ 384 | "killed": false␊ 385 | }␊ 386 | ]␊ 387 | [12:00:00] Finished 'inputFile' after 100 ms`, 388 | } 389 | 390 | ## stream() | stream-save {"task": "inputUndefined"} 391 | 392 | > Snapshot 1 393 | 394 | { 395 | exitCode: 0, 396 | stderr: '', 397 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 398 | []␊ 399 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 400 | } 401 | 402 | ## stream() | stream-save {"task": "severalFiles"} 403 | 404 | > Snapshot 1 405 | 406 | { 407 | exitCode: 0, 408 | stderr: '', 409 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 410 | [␊ 411 | {␊ 412 | "command": "echo test",␊ 413 | "escapedCommand": "echo test",␊ 414 | "exitCode": 0,␊ 415 | "stdout": "test",␊ 416 | "stderr": "",␊ 417 | "failed": false,␊ 418 | "timedOut": false,␊ 419 | "isCanceled": false,␊ 420 | "killed": false␊ 421 | }␊ 422 | ]␊ 423 | [␊ 424 | {␊ 425 | "command": "echo test",␊ 426 | "escapedCommand": "echo test",␊ 427 | "exitCode": 0,␊ 428 | "stdout": "test",␊ 429 | "stderr": "",␊ 430 | "failed": false,␊ 431 | "timedOut": false,␊ 432 | "isCanceled": false,␊ 433 | "killed": false␊ 434 | }␊ 435 | ]␊ 436 | [12:00:00] Finished 'severalFiles' after 100 ms`, 437 | } 438 | 439 | ## stream() | stream-save {"task": "severalTimes"} 440 | 441 | > Snapshot 1 442 | 443 | { 444 | exitCode: 0, 445 | stderr: '', 446 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 447 | [␊ 448 | {␊ 449 | "command": "echo test",␊ 450 | "escapedCommand": "echo test",␊ 451 | "exitCode": 0,␊ 452 | "stdout": "test",␊ 453 | "stderr": "",␊ 454 | "failed": false,␊ 455 | "timedOut": false,␊ 456 | "isCanceled": false,␊ 457 | "killed": false␊ 458 | },␊ 459 | {␊ 460 | "command": "echo test",␊ 461 | "escapedCommand": "echo test",␊ 462 | "exitCode": 0,␊ 463 | "stdout": "test",␊ 464 | "stderr": "",␊ 465 | "failed": false,␊ 466 | "timedOut": false,␊ 467 | "isCanceled": false,␊ 468 | "killed": false␊ 469 | }␊ 470 | ]␊ 471 | [12:00:00] Finished 'severalTimes' after 100 ms`, 472 | } 473 | 474 | ## stream() | stream-save {} 475 | 476 | > Snapshot 1 477 | 478 | { 479 | exitCode: 0, 480 | stderr: '', 481 | stdout: `[12:00:00] Starting 'main'...␊ 482 | [␊ 483 | {␊ 484 | "command": "echo test",␊ 485 | "escapedCommand": "echo test",␊ 486 | "exitCode": 0,␊ 487 | "stdout": "test",␊ 488 | "stderr": "",␊ 489 | "failed": false,␊ 490 | "timedOut": false,␊ 491 | "isCanceled": false,␊ 492 | "killed": false␊ 493 | }␊ 494 | ]␊ 495 | [12:00:00] Finished 'main' after 100 ms`, 496 | } 497 | 498 | ## stream() | stream-save {"command": {"command": "echo test", "stripFinalNewline": true}} 499 | 500 | > Snapshot 1 501 | 502 | { 503 | exitCode: 0, 504 | stderr: '', 505 | stdout: `[12:00:00] Starting 'main'...␊ 506 | [␊ 507 | {␊ 508 | "command": "echo test",␊ 509 | "escapedCommand": "echo test",␊ 510 | "exitCode": 0,␊ 511 | "stdout": "test",␊ 512 | "stderr": "",␊ 513 | "failed": false,␊ 514 | "timedOut": false,␊ 515 | "isCanceled": false,␊ 516 | "killed": false␊ 517 | }␊ 518 | ]␊ 519 | [12:00:00] Finished 'main' after 100 ms`, 520 | } 521 | 522 | ## stream() | stream-save {"opts": {"encoding": "utf8"}} 523 | 524 | > Snapshot 1 525 | 526 | { 527 | exitCode: 0, 528 | stderr: '', 529 | stdout: `[12:00:00] Starting 'main'...␊ 530 | [␊ 531 | {␊ 532 | "command": "echo test",␊ 533 | "escapedCommand": "echo test",␊ 534 | "exitCode": 0,␊ 535 | "stdout": "test",␊ 536 | "stderr": "",␊ 537 | "failed": false,␊ 538 | "timedOut": false,␊ 539 | "isCanceled": false,␊ 540 | "killed": false␊ 541 | }␊ 542 | ]␊ 543 | [12:00:00] Finished 'main' after 100 ms`, 544 | } 545 | 546 | ## stream() | stream-save {"opts": {"stripFinalNewline": true}} 547 | 548 | > Snapshot 1 549 | 550 | { 551 | exitCode: 0, 552 | stderr: '', 553 | stdout: `[12:00:00] Starting 'main'...␊ 554 | [␊ 555 | {␊ 556 | "command": "echo test",␊ 557 | "escapedCommand": "echo test",␊ 558 | "exitCode": 0,␊ 559 | "stdout": "test",␊ 560 | "stderr": "",␊ 561 | "failed": false,␊ 562 | "timedOut": false,␊ 563 | "isCanceled": false,␊ 564 | "killed": false␊ 565 | }␊ 566 | ]␊ 567 | [12:00:00] Finished 'main' after 100 ms`, 568 | } 569 | -------------------------------------------------------------------------------- /src/snapshots/build/src/stream.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/stream.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/stream/main.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/stream/main.test.js` 2 | 3 | The actual snapshot is saved in `main.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## stream() | stream-buffer {"task": "inputNotFunc"} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 1, 13 | stderr: `Option 'getInput' must be a function: echo test␊ 14 | at STACK TRACE`, 15 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 16 | } 17 | 18 | ## stream() | stream-buffer {"task": "inputThrows"} 19 | 20 | > Snapshot 1 21 | 22 | { 23 | exitCode: 1, 24 | stderr: `error␊ 25 | at STACK TRACE`, 26 | stdout: '[12:00:00] Starting \'inputThrows\'...', 27 | } 28 | 29 | ## stream() | stream-buffer {"task": "inputThrowsAsync"} 30 | 31 | > Snapshot 1 32 | 33 | { 34 | exitCode: 1, 35 | stderr: `error␊ 36 | at STACK TRACE`, 37 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 38 | } 39 | 40 | ## stream() | stream-buffer {"task": "inputAsync"} 41 | 42 | > Snapshot 1 43 | 44 | { 45 | exitCode: 0, 46 | stderr: '', 47 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 48 | test␊ 49 | ␊ 50 | [12:00:00] Finished 'inputAsync' after 100 ms`, 51 | } 52 | 53 | ## stream() | stream-buffer {"command": "echo", "task": "inputFile"} 54 | 55 | > Snapshot 1 56 | 57 | { 58 | exitCode: 0, 59 | stderr: '', 60 | stdout: `[12:00:00] Starting 'inputFile'...␊ 61 | dummy.txt␊ 62 | ␊ 63 | [12:00:00] Finished 'inputFile' after 100 ms`, 64 | } 65 | 66 | ## stream() | stream-buffer {"task": "inputUndefined"} 67 | 68 | > Snapshot 1 69 | 70 | { 71 | exitCode: 0, 72 | stderr: '', 73 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 74 | one␊ 75 | ␊ 76 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 77 | } 78 | 79 | ## stream() | stream-buffer {"task": "severalFiles"} 80 | 81 | > Snapshot 1 82 | 83 | { 84 | exitCode: 0, 85 | stderr: '', 86 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 87 | test␊ 88 | ␊ 89 | test␊ 90 | ␊ 91 | [12:00:00] Finished 'severalFiles' after 100 ms`, 92 | } 93 | 94 | ## stream() | stream-buffer {"task": "severalTimes"} 95 | 96 | > Snapshot 1 97 | 98 | { 99 | exitCode: 0, 100 | stderr: '', 101 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 102 | test␊ 103 | ␊ 104 | [12:00:00] Finished 'severalTimes' after 100 ms`, 105 | } 106 | 107 | ## stream() | stream-buffer {} 108 | 109 | > Snapshot 1 110 | 111 | { 112 | exitCode: 0, 113 | stderr: '', 114 | stdout: `[12:00:00] Starting 'main'...␊ 115 | test␊ 116 | ␊ 117 | [12:00:00] Finished 'main' after 100 ms`, 118 | } 119 | 120 | ## stream() | stream-buffer {"command": {"command": "echo test", "stripFinalNewline": true}} 121 | 122 | > Snapshot 1 123 | 124 | { 125 | exitCode: 0, 126 | stderr: '', 127 | stdout: `[12:00:00] Starting 'main'...␊ 128 | test␊ 129 | [12:00:00] Finished 'main' after 100 ms`, 130 | } 131 | 132 | ## stream() | stream-buffer {"opts": {"encoding": "utf8"}} 133 | 134 | > Snapshot 1 135 | 136 | { 137 | exitCode: 0, 138 | stderr: '', 139 | stdout: `[12:00:00] Starting 'main'...␊ 140 | test␊ 141 | ␊ 142 | [12:00:00] Finished 'main' after 100 ms`, 143 | } 144 | 145 | ## stream() | stream-buffer {"opts": {"stripFinalNewline": true}} 146 | 147 | > Snapshot 1 148 | 149 | { 150 | exitCode: 0, 151 | stderr: '', 152 | stdout: `[12:00:00] Starting 'main'...␊ 153 | test␊ 154 | [12:00:00] Finished 'main' after 100 ms`, 155 | } 156 | 157 | ## stream() | stream-stream {"task": "inputNotFunc"} 158 | 159 | > Snapshot 1 160 | 161 | { 162 | exitCode: 1, 163 | stderr: `Option 'getInput' must be a function: echo test␊ 164 | at STACK TRACE`, 165 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 166 | } 167 | 168 | ## stream() | stream-stream {"task": "inputThrows"} 169 | 170 | > Snapshot 1 171 | 172 | { 173 | exitCode: 1, 174 | stderr: `error␊ 175 | at STACK TRACE`, 176 | stdout: '[12:00:00] Starting \'inputThrows\'...', 177 | } 178 | 179 | ## stream() | stream-stream {"task": "inputThrowsAsync"} 180 | 181 | > Snapshot 1 182 | 183 | { 184 | exitCode: 1, 185 | stderr: `error␊ 186 | at STACK TRACE`, 187 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 188 | } 189 | 190 | ## stream() | stream-stream {"task": "inputAsync"} 191 | 192 | > Snapshot 1 193 | 194 | { 195 | exitCode: 0, 196 | stderr: '', 197 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 198 | test␊ 199 | ␊ 200 | [12:00:00] Finished 'inputAsync' after 100 ms`, 201 | } 202 | 203 | ## stream() | stream-stream {"command": "echo", "task": "inputFile"} 204 | 205 | > Snapshot 1 206 | 207 | { 208 | exitCode: 0, 209 | stderr: '', 210 | stdout: `[12:00:00] Starting 'inputFile'...␊ 211 | dummy.txt␊ 212 | ␊ 213 | [12:00:00] Finished 'inputFile' after 100 ms`, 214 | } 215 | 216 | ## stream() | stream-stream {"task": "inputUndefined"} 217 | 218 | > Snapshot 1 219 | 220 | { 221 | exitCode: 0, 222 | stderr: '', 223 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 224 | one␊ 225 | ␊ 226 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 227 | } 228 | 229 | ## stream() | stream-stream {"task": "severalFiles"} 230 | 231 | > Snapshot 1 232 | 233 | { 234 | exitCode: 0, 235 | stderr: '', 236 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 237 | test␊ 238 | ␊ 239 | test␊ 240 | ␊ 241 | [12:00:00] Finished 'severalFiles' after 100 ms`, 242 | } 243 | 244 | ## stream() | stream-stream {"task": "severalTimes"} 245 | 246 | > Snapshot 1 247 | 248 | { 249 | exitCode: 0, 250 | stderr: '', 251 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 252 | test␊ 253 | ␊ 254 | [12:00:00] Finished 'severalTimes' after 100 ms`, 255 | } 256 | 257 | ## stream() | stream-stream {} 258 | 259 | > Snapshot 1 260 | 261 | { 262 | exitCode: 0, 263 | stderr: '', 264 | stdout: `[12:00:00] Starting 'main'...␊ 265 | test␊ 266 | ␊ 267 | [12:00:00] Finished 'main' after 100 ms`, 268 | } 269 | 270 | ## stream() | stream-stream {"command": {"command": "echo test", "stripFinalNewline": true}} 271 | 272 | > Snapshot 1 273 | 274 | { 275 | exitCode: 0, 276 | stderr: '', 277 | stdout: `[12:00:00] Starting 'main'...␊ 278 | test␊ 279 | ␊ 280 | [12:00:00] Finished 'main' after 100 ms`, 281 | } 282 | 283 | ## stream() | stream-stream {"opts": {"encoding": "utf8"}} 284 | 285 | > Snapshot 1 286 | 287 | { 288 | exitCode: 0, 289 | stderr: '', 290 | stdout: `[12:00:00] Starting 'main'...␊ 291 | test␊ 292 | ␊ 293 | [12:00:00] Finished 'main' after 100 ms`, 294 | } 295 | 296 | ## stream() | stream-stream {"opts": {"stripFinalNewline": true}} 297 | 298 | > Snapshot 1 299 | 300 | { 301 | exitCode: 0, 302 | stderr: '', 303 | stdout: `[12:00:00] Starting 'main'...␊ 304 | test␊ 305 | ␊ 306 | [12:00:00] Finished 'main' after 100 ms`, 307 | } 308 | 309 | ## stream() | stream-save {"task": "inputNotFunc"} 310 | 311 | > Snapshot 1 312 | 313 | { 314 | exitCode: 1, 315 | stderr: `Option 'getInput' must be a function: echo test␊ 316 | at STACK TRACE`, 317 | stdout: '[12:00:00] Starting \'inputNotFunc\'...', 318 | } 319 | 320 | ## stream() | stream-save {"task": "inputThrows"} 321 | 322 | > Snapshot 1 323 | 324 | { 325 | exitCode: 1, 326 | stderr: `error␊ 327 | at STACK TRACE`, 328 | stdout: '[12:00:00] Starting \'inputThrows\'...', 329 | } 330 | 331 | ## stream() | stream-save {"task": "inputThrowsAsync"} 332 | 333 | > Snapshot 1 334 | 335 | { 336 | exitCode: 1, 337 | stderr: `error␊ 338 | at STACK TRACE`, 339 | stdout: '[12:00:00] Starting \'inputThrowsAsync\'...', 340 | } 341 | 342 | ## stream() | stream-save {"task": "inputAsync"} 343 | 344 | > Snapshot 1 345 | 346 | { 347 | exitCode: 0, 348 | stderr: '', 349 | stdout: `[12:00:00] Starting 'inputAsync'...␊ 350 | [␊ 351 | {␊ 352 | "command": "echo test",␊ 353 | "escapedCommand": "echo test",␊ 354 | "cwd": /path␊ 355 | "durationMs": 1,␊ 356 | "failed": false,␊ 357 | "timedOut": false,␊ 358 | "isCanceled": false,␊ 359 | "isGracefullyCanceled": false,␊ 360 | "isTerminated": false,␊ 361 | "isMaxBuffer": false,␊ 362 | "isForcefullyTerminated": false,␊ 363 | "exitCode": 0,␊ 364 | "stdout": "test",␊ 365 | "stderr": "",␊ 366 | "stdio": [␊ 367 | null,␊ 368 | "test",␊ 369 | ""␊ 370 | ],␊ 371 | "ipcOutput": [],␊ 372 | "pipedFrom": []␊ 373 | }␊ 374 | ]␊ 375 | [12:00:00] Finished 'inputAsync' after 100 ms`, 376 | } 377 | 378 | ## stream() | stream-save {"command": "echo", "task": "inputFile"} 379 | 380 | > Snapshot 1 381 | 382 | { 383 | exitCode: 0, 384 | stderr: '', 385 | stdout: `[12:00:00] Starting 'inputFile'...␊ 386 | [␊ 387 | {␊ 388 | "command": "echo dummy.txt",␊ 389 | "escapedCommand": "echo dummy.txt",␊ 390 | "cwd": /path␊ 391 | "durationMs": 1,␊ 392 | "failed": false,␊ 393 | "timedOut": false,␊ 394 | "isCanceled": false,␊ 395 | "isGracefullyCanceled": false,␊ 396 | "isTerminated": false,␊ 397 | "isMaxBuffer": false,␊ 398 | "isForcefullyTerminated": false,␊ 399 | "exitCode": 0,␊ 400 | "stdout": "dummy.txt",␊ 401 | "stderr": "",␊ 402 | "stdio": [␊ 403 | null,␊ 404 | "dummy.txt",␊ 405 | ""␊ 406 | ],␊ 407 | "ipcOutput": [],␊ 408 | "pipedFrom": []␊ 409 | }␊ 410 | ]␊ 411 | [12:00:00] Finished 'inputFile' after 100 ms`, 412 | } 413 | 414 | ## stream() | stream-save {"task": "inputUndefined"} 415 | 416 | > Snapshot 1 417 | 418 | { 419 | exitCode: 0, 420 | stderr: '', 421 | stdout: `[12:00:00] Starting 'inputUndefined'...␊ 422 | []␊ 423 | [12:00:00] Finished 'inputUndefined' after 100 ms`, 424 | } 425 | 426 | ## stream() | stream-save {"task": "severalFiles"} 427 | 428 | > Snapshot 1 429 | 430 | { 431 | exitCode: 0, 432 | stderr: '', 433 | stdout: `[12:00:00] Starting 'severalFiles'...␊ 434 | [␊ 435 | {␊ 436 | "command": "echo test",␊ 437 | "escapedCommand": "echo test",␊ 438 | "cwd": /path␊ 439 | "durationMs": 1,␊ 440 | "failed": false,␊ 441 | "timedOut": false,␊ 442 | "isCanceled": false,␊ 443 | "isGracefullyCanceled": false,␊ 444 | "isTerminated": false,␊ 445 | "isMaxBuffer": false,␊ 446 | "isForcefullyTerminated": false,␊ 447 | "exitCode": 0,␊ 448 | "stdout": "test",␊ 449 | "stderr": "",␊ 450 | "stdio": [␊ 451 | null,␊ 452 | "test",␊ 453 | ""␊ 454 | ],␊ 455 | "ipcOutput": [],␊ 456 | "pipedFrom": []␊ 457 | }␊ 458 | ]␊ 459 | [␊ 460 | {␊ 461 | "command": "echo test",␊ 462 | "escapedCommand": "echo test",␊ 463 | "cwd": /path␊ 464 | "durationMs": 1,␊ 465 | "failed": false,␊ 466 | "timedOut": false,␊ 467 | "isCanceled": false,␊ 468 | "isGracefullyCanceled": false,␊ 469 | "isTerminated": false,␊ 470 | "isMaxBuffer": false,␊ 471 | "isForcefullyTerminated": false,␊ 472 | "exitCode": 0,␊ 473 | "stdout": "test",␊ 474 | "stderr": "",␊ 475 | "stdio": [␊ 476 | null,␊ 477 | "test",␊ 478 | ""␊ 479 | ],␊ 480 | "ipcOutput": [],␊ 481 | "pipedFrom": []␊ 482 | }␊ 483 | ]␊ 484 | [12:00:00] Finished 'severalFiles' after 100 ms`, 485 | } 486 | 487 | ## stream() | stream-save {"task": "severalTimes"} 488 | 489 | > Snapshot 1 490 | 491 | { 492 | exitCode: 0, 493 | stderr: '', 494 | stdout: `[12:00:00] Starting 'severalTimes'...␊ 495 | [␊ 496 | {␊ 497 | "command": "echo test",␊ 498 | "escapedCommand": "echo test",␊ 499 | "cwd": /path␊ 500 | "durationMs": 1,␊ 501 | "failed": false,␊ 502 | "timedOut": false,␊ 503 | "isCanceled": false,␊ 504 | "isGracefullyCanceled": false,␊ 505 | "isTerminated": false,␊ 506 | "isMaxBuffer": false,␊ 507 | "isForcefullyTerminated": false,␊ 508 | "exitCode": 0,␊ 509 | "stdout": "test",␊ 510 | "stderr": "",␊ 511 | "stdio": [␊ 512 | null,␊ 513 | "test",␊ 514 | ""␊ 515 | ],␊ 516 | "ipcOutput": [],␊ 517 | "pipedFrom": []␊ 518 | },␊ 519 | {␊ 520 | "command": "echo test",␊ 521 | "escapedCommand": "echo test",␊ 522 | "cwd": /path␊ 523 | "durationMs": 1,␊ 524 | "failed": false,␊ 525 | "timedOut": false,␊ 526 | "isCanceled": false,␊ 527 | "isGracefullyCanceled": false,␊ 528 | "isTerminated": false,␊ 529 | "isMaxBuffer": false,␊ 530 | "isForcefullyTerminated": false,␊ 531 | "exitCode": 0,␊ 532 | "stdout": "test",␊ 533 | "stderr": "",␊ 534 | "stdio": [␊ 535 | null,␊ 536 | "test",␊ 537 | ""␊ 538 | ],␊ 539 | "ipcOutput": [],␊ 540 | "pipedFrom": []␊ 541 | }␊ 542 | ]␊ 543 | [12:00:00] Finished 'severalTimes' after 100 ms`, 544 | } 545 | 546 | ## stream() | stream-save {} 547 | 548 | > Snapshot 1 549 | 550 | { 551 | exitCode: 0, 552 | stderr: '', 553 | stdout: `[12:00:00] Starting 'main'...␊ 554 | [␊ 555 | {␊ 556 | "command": "echo test",␊ 557 | "escapedCommand": "echo test",␊ 558 | "cwd": /path␊ 559 | "durationMs": 1,␊ 560 | "failed": false,␊ 561 | "timedOut": false,␊ 562 | "isCanceled": false,␊ 563 | "isGracefullyCanceled": false,␊ 564 | "isTerminated": false,␊ 565 | "isMaxBuffer": false,␊ 566 | "isForcefullyTerminated": false,␊ 567 | "exitCode": 0,␊ 568 | "stdout": "test",␊ 569 | "stderr": "",␊ 570 | "stdio": [␊ 571 | null,␊ 572 | "test",␊ 573 | ""␊ 574 | ],␊ 575 | "ipcOutput": [],␊ 576 | "pipedFrom": []␊ 577 | }␊ 578 | ]␊ 579 | [12:00:00] Finished 'main' after 100 ms`, 580 | } 581 | 582 | ## stream() | stream-save {"command": {"command": "echo test", "stripFinalNewline": true}} 583 | 584 | > Snapshot 1 585 | 586 | { 587 | exitCode: 0, 588 | stderr: '', 589 | stdout: `[12:00:00] Starting 'main'...␊ 590 | [␊ 591 | {␊ 592 | "command": "echo test",␊ 593 | "escapedCommand": "echo test",␊ 594 | "cwd": /path␊ 595 | "durationMs": 1,␊ 596 | "failed": false,␊ 597 | "timedOut": false,␊ 598 | "isCanceled": false,␊ 599 | "isGracefullyCanceled": false,␊ 600 | "isTerminated": false,␊ 601 | "isMaxBuffer": false,␊ 602 | "isForcefullyTerminated": false,␊ 603 | "exitCode": 0,␊ 604 | "stdout": "test",␊ 605 | "stderr": "",␊ 606 | "stdio": [␊ 607 | null,␊ 608 | "test",␊ 609 | ""␊ 610 | ],␊ 611 | "ipcOutput": [],␊ 612 | "pipedFrom": []␊ 613 | }␊ 614 | ]␊ 615 | [12:00:00] Finished 'main' after 100 ms`, 616 | } 617 | 618 | ## stream() | stream-save {"opts": {"encoding": "utf8"}} 619 | 620 | > Snapshot 1 621 | 622 | { 623 | exitCode: 0, 624 | stderr: '', 625 | stdout: `[12:00:00] Starting 'main'...␊ 626 | [␊ 627 | {␊ 628 | "command": "echo test",␊ 629 | "escapedCommand": "echo test",␊ 630 | "cwd": /path␊ 631 | "durationMs": 1,␊ 632 | "failed": false,␊ 633 | "timedOut": false,␊ 634 | "isCanceled": false,␊ 635 | "isGracefullyCanceled": false,␊ 636 | "isTerminated": false,␊ 637 | "isMaxBuffer": false,␊ 638 | "isForcefullyTerminated": false,␊ 639 | "exitCode": 0,␊ 640 | "stdout": "test",␊ 641 | "stderr": "",␊ 642 | "stdio": [␊ 643 | null,␊ 644 | "test",␊ 645 | ""␊ 646 | ],␊ 647 | "ipcOutput": [],␊ 648 | "pipedFrom": []␊ 649 | }␊ 650 | ]␊ 651 | [12:00:00] Finished 'main' after 100 ms`, 652 | } 653 | 654 | ## stream() | stream-save {"opts": {"stripFinalNewline": true}} 655 | 656 | > Snapshot 1 657 | 658 | { 659 | exitCode: 0, 660 | stderr: '', 661 | stdout: `[12:00:00] Starting 'main'...␊ 662 | [␊ 663 | {␊ 664 | "command": "echo test",␊ 665 | "escapedCommand": "echo test",␊ 666 | "cwd": /path␊ 667 | "durationMs": 1,␊ 668 | "failed": false,␊ 669 | "timedOut": false,␊ 670 | "isCanceled": false,␊ 671 | "isGracefullyCanceled": false,␊ 672 | "isTerminated": false,␊ 673 | "isMaxBuffer": false,␊ 674 | "isForcefullyTerminated": false,␊ 675 | "exitCode": 0,␊ 676 | "stdout": "test",␊ 677 | "stderr": "",␊ 678 | "stdio": [␊ 679 | null,␊ 680 | "test",␊ 681 | ""␊ 682 | ],␊ 683 | "ipcOutput": [],␊ 684 | "pipedFrom": []␊ 685 | }␊ 686 | ]␊ 687 | [12:00:00] Finished 'main' after 100 ms`, 688 | } 689 | -------------------------------------------------------------------------------- /src/snapshots/build/src/stream/main.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/stream/main.test.js.snap -------------------------------------------------------------------------------- /src/snapshots/build/src/task.test.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `build/src/task.test.js` 2 | 3 | The actual snapshot is saved in `task.test.js.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## task() | task {} 8 | 9 | > Snapshot 1 10 | 11 | { 12 | exitCode: 0, 13 | stderr: '', 14 | stdout: `[12:00:00] Starting 'main'...␊ 15 | [12:00:00] [gulp-execa] echo test␊ 16 | test␊ 17 | [12:00:00] Finished 'main' after 100 ms`, 18 | } 19 | 20 | ## task() | task {"task": "nested"} 21 | 22 | > Snapshot 1 23 | 24 | { 25 | exitCode: 0, 26 | stderr: '', 27 | stdout: `[12:00:00] Starting 'nested'...␊ 28 | [12:00:00] Starting 'echo test'...␊ 29 | [12:00:00] [gulp-execa] echo test␊ 30 | test␊ 31 | [12:00:00] Finished 'echo test' after 100 ms␊ 32 | [12:00:00] Finished 'nested' after 100 ms`, 33 | } 34 | -------------------------------------------------------------------------------- /src/snapshots/build/src/task.test.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ehmicky/gulp-execa/162bceb970a63990c18a11b9a004e393d2a7b1eb/src/snapshots/build/src/task.test.js.snap -------------------------------------------------------------------------------- /src/stream/main.js: -------------------------------------------------------------------------------- 1 | import { callbackify } from 'node:util' 2 | 3 | import isPlainObj from 'is-plain-obj' 4 | import through from 'through2-concurrent' 5 | 6 | import { throwError } from '../error.js' 7 | import { parseOpts } from '../options/main.js' 8 | 9 | import { forcedOpts, getDefaultOpts } from './options.js' 10 | import { setResult } from './result.js' 11 | 12 | // Creates a stream that fires child processes on each file: 13 | // pipeline(gulp.src(...), stream(({ path }) => `command ${path}`)) 14 | export const stream = (getInput, opts) => { 15 | validateGetInput(getInput) 16 | 17 | const defaultOpts = getDefaultOpts({ opts }) 18 | const { 19 | maxConcurrency, 20 | result: resultOpt, 21 | ...optsA 22 | } = parseOpts({ 23 | opts, 24 | defaultOpts, 25 | forcedOpts, 26 | }) 27 | 28 | return through.obj( 29 | { maxConcurrency }, 30 | execVinyl.bind(undefined, { getInput, opts: optsA, resultOpt }), 31 | ) 32 | } 33 | 34 | const validateGetInput = (getInput) => { 35 | if (typeof getInput !== 'function') { 36 | throwError(`Option 'getInput' must be a function: ${getInput}`) 37 | } 38 | } 39 | 40 | const cExecVinyl = async ({ getInput, opts, resultOpt }, file) => { 41 | const { input, opts: optsA } = await getFileInput({ getInput, file, opts }) 42 | 43 | await setResult({ file, input, opts: optsA, resultOpt }) 44 | 45 | return file 46 | } 47 | 48 | const execVinyl = callbackify(cExecVinyl) 49 | 50 | // `getInput()` can either return the command as string, or the 51 | // command + its options as object. 52 | const getFileInput = async ({ getInput, file, opts }) => { 53 | const result = await getInputResult({ getInput, file }) 54 | 55 | if (isPlainObj(result)) { 56 | const { command, ...fileOpts } = result 57 | return { input: command, opts: { ...opts, ...fileOpts } } 58 | } 59 | 60 | if (typeof result === 'string') { 61 | return { input: result, opts } 62 | } 63 | 64 | return { opts } 65 | } 66 | 67 | const getInputResult = ({ getInput, file }) => { 68 | try { 69 | return getInput(file) 70 | } catch (error) { 71 | throwError(error) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/stream/main.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { STREAM_METHODS } from '../helpers/methods.test.js' 5 | import { snapshotTest } from '../helpers/snapshot.test.js' 6 | 7 | each( 8 | STREAM_METHODS, 9 | [ 10 | { task: 'inputNotFunc' }, 11 | { task: 'inputThrows' }, 12 | { task: 'inputThrowsAsync' }, 13 | { task: 'inputAsync' }, 14 | { task: 'inputFile', command: 'echo' }, 15 | { task: 'inputUndefined' }, 16 | { task: 'severalFiles' }, 17 | { task: 'severalTimes' }, 18 | {}, 19 | { command: { command: 'echo test', stripFinalNewline: true } }, 20 | { opts: { encoding: 'utf8' } }, 21 | { opts: { stripFinalNewline: true } }, 22 | ], 23 | ({ title }, methodProps, data) => 24 | test(`stream() | ${title}`, async (t) => { 25 | await snapshotTest({ t, methodProps, data }) 26 | }), 27 | ) 28 | -------------------------------------------------------------------------------- /src/stream/options.js: -------------------------------------------------------------------------------- 1 | export const getDefaultOpts = ({ 2 | opts: { result = 'replace', from } = {}, 3 | }) => ({ 4 | // This is too verbose if done on each iteration, even on CI 5 | debug: false, 6 | // We use `through2-concurrent` because `through2` processes files serially. 7 | // The default is 16 which is too low. 8 | maxConcurrency: 100, 9 | // What to do with the result. Either 'save' or 'replace'. 10 | result: 'replace', 11 | // With `result: 'replace'` which stream to use: `stdout`, `stderr` or `all` 12 | from: 'stdout', 13 | // `from: 'all`` requires the `all` option 14 | all: from === 'all', 15 | ...resultDefaultOpts[result], 16 | }) 17 | 18 | const resultDefaultOpts = { 19 | // `save` should retrieve output as string, but this is not needed for 20 | // `replace`. Same thing with final newline stripping. 21 | replace: { encoding: 'buffer', stripFinalNewline: false }, 22 | } 23 | 24 | export const forcedOpts = { 25 | // Forces piping stdout|stderr because: 26 | // - `inherit` would be too verbose if done on each iteration. 27 | // - `save` mode would not get `stdout|stderr|all` properties. 28 | // - `replace` mode would not work. 29 | stdout: 'pipe', 30 | stderr: 'pipe', 31 | // `stdio` cannot be combined with `stdout|stderr` with execa 32 | stdio: undefined, 33 | } 34 | -------------------------------------------------------------------------------- /src/stream/result.js: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'node:buffer' 2 | 3 | import { execCommand, streamCommand } from '../exec.js' 4 | import { isValidInput } from '../input.js' 5 | 6 | // Decides what to do with the child process result according to `opts.result`: 7 | // - `save`: pushed to `file.execa` 8 | // - `replace`: overwrite file's content 9 | export const setResult = ({ file, input, opts, resultOpt }) => { 10 | initSave({ file, resultOpt }) 11 | 12 | // Returning `undefined` or invalid command skips it silently. 13 | if (!isValidInput(input)) { 14 | return 15 | } 16 | 17 | if (resultOpt === 'save') { 18 | return saveResult({ file, input, opts }) 19 | } 20 | 21 | // If the `file` already uses streams, we do it as well as it's more 22 | // efficient. This is done usually by using `gulp.src(..., { buffer: false })` 23 | // Otherwise we don't since many Gulp plugins don't support `file.contents` 24 | // being a stream. 25 | if (file.isStream()) { 26 | return streamResult({ file, input, opts }) 27 | } 28 | 29 | return bufferResult({ file, input, opts }) 30 | } 31 | 32 | // Make sure `file.execa` is always set even if all inputs are invalid 33 | const initSave = ({ file, file: { execa }, resultOpt }) => { 34 | if (resultOpt !== 'save' || execa !== undefined) { 35 | return 36 | } 37 | 38 | // eslint-disable-next-line no-param-reassign, fp/no-mutation 39 | file.execa = [] 40 | } 41 | 42 | const saveResult = async ({ file, file: { execa }, input, opts }) => { 43 | const execaResult = await execCommand(input, opts) 44 | // eslint-disable-next-line no-param-reassign, fp/no-mutation 45 | file.execa = [...execa, execaResult] 46 | } 47 | 48 | const streamResult = ({ file, input, opts }) => { 49 | // eslint-disable-next-line no-param-reassign, fp/no-mutation 50 | file.contents = streamCommand(input, opts) 51 | } 52 | 53 | const bufferResult = async ({ file, input, opts, opts: { from } }) => { 54 | const { [from]: output } = await execCommand(input, opts) 55 | // Stream output can be either string or buffer depending on `opts.encoding` 56 | // However `file.contents` cannot be a string. 57 | // eslint-disable-next-line no-param-reassign, fp/no-mutation 58 | file.contents = Buffer.from(output) 59 | } 60 | -------------------------------------------------------------------------------- /src/task.js: -------------------------------------------------------------------------------- 1 | import renameFn from 'rename-fn' 2 | 3 | import { execCommand } from './exec.js' 4 | import { validateInput } from './input.js' 5 | import { parseOpts } from './options/main.js' 6 | 7 | // Create a Gulp task that fires a child process (command + arguments) 8 | export const task = (input, opts) => { 9 | try { 10 | validateInput(input) 11 | const optsA = parseOpts({ opts }) 12 | 13 | const gulpTask = execCommand.bind(undefined, input, optsA) 14 | 15 | // Log the command and arguments as the task name. 16 | // This does not work when this is the top-level task. 17 | renameFn(gulpTask, input) 18 | 19 | return gulpTask 20 | } catch (error) { 21 | handleTask(error) 22 | } 23 | } 24 | 25 | // Since Node 12.3.0, uncaught exceptions also print their properties when they 26 | // are instances of custom errors. This makes input|options validation errors 27 | // of `task()` (which are likely to become uncaught exceptions) not print as 28 | // nicely. We fix this by re-throwing the error but with a normal `Error`. 29 | const handleTask = (error) => { 30 | const errorA = new Error(error.message) 31 | // eslint-disable-next-line fp/no-mutation 32 | errorA.stack = error.stack 33 | throw errorA 34 | } 35 | -------------------------------------------------------------------------------- /src/task.test.js: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { each } from 'test-each' 3 | 4 | import { TASK_METHODS } from './helpers/methods.test.js' 5 | import { snapshotTest } from './helpers/snapshot.test.js' 6 | 7 | each(TASK_METHODS, [{}, { task: 'nested' }], ({ title }, methodProps, data) => 8 | test(`task() | ${title}`, async (t) => { 9 | await snapshotTest({ t, methodProps, data }) 10 | }), 11 | ) 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@ehmicky/dev-tasks/tsconfig.json" 3 | } 4 | --------------------------------------------------------------------------------