├── .editorconfig
├── .eslintrc.json
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── docs
├── API.md
├── CLI.md
├── README.md
├── REPL.md
├── arguments.md
└── logging.md
├── examples
├── cli-as-tasks.js
├── functions-as-tasks.js
├── gulpfile.js
├── logging.js
├── pass-arguments.js
├── src
│ └── file.js
└── task-parameters.js
├── index.js
├── lib
├── cli.js
└── util.js
├── package.json
└── test
├── cli.js
├── create.js
├── index.js
├── task.js
├── util.js
└── watch.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true,
4 | "mocha": true
5 | },
6 | "rules": {
7 | "strict": 2,
8 | "quotes": [2, "single", "avoid-escape"],
9 | "indent": ["error", 2, {"SwitchCase": 1}],
10 | "eol-last": 2,
11 | "no-shadow": 2,
12 | "dot-notation": 2,
13 | "dot-location": [2, "property"],
14 | "comma-dangle": [2, "never"],
15 | "no-unused-vars": 2,
16 | "keyword-spacing": 2,
17 | "no-multi-spaces": 2,
18 | "no-process-exit": 0,
19 | "keyword-spacing": 2,
20 | "consistent-return": 0,
21 | "space-before-blocks": 2,
22 | "no-use-before-define": 0,
23 | "no-underscore-dangle": 0,
24 | "no-unused-expressions": 2,
25 | "space-before-function-paren": 2
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | test/dir/**
3 | examples/build
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 | - "stable"
5 | notifications:
6 | email: true
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This software is released under the MIT license:
2 |
3 | Copyright (c) 2014-present Javier Carrillo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## gulp-runtime [![NPM version][badge-version]][npm] [![downloads][badge-downloads]][npm]
2 |
3 | [![build][badge-build]][travis-build]
4 |
5 | 
6 |
7 | [documentation](docs/README.md) -
8 | [install](#install) -
9 | [setup](docs/README.md#setup) -
10 | [why](#why)
11 |
12 | ### features
13 |
14 | - [gulp API and more](docs/API.md)
15 | - [customizable logging](docs/logging.md)
16 | - [REPL with autocomplete](docs/REPL.md)
17 | - [Tasks :names with :parameters](docs/task-parameters.md)
18 | - [pass arguments from the task runner](docs/task-arguments.md)
19 |
20 | ### samples
21 |
22 | #### CLI as tasks
23 |
24 | ```js
25 | var gulp = require('gulp-runtime').create();
26 |
27 | gulp.task('default', ['--tasks', '--version']);
28 | ```
29 |
30 | #### task :parameters
31 |
32 | ```js
33 | var gulp = require('gulp-runtime').create();
34 |
35 | gulp.task('build :src :dest', function () {
36 | return gulp.src(this.params.src)
37 | // transform, compress, etc.
38 | .pipe(gulp.dest(this.params.dest));
39 | });
40 |
41 | gulp.task('default',
42 | gulp.parallel('build src/**/*.js build')
43 | );
44 | ```
45 |
46 | #### passing arguments
47 |
48 | ```js
49 | var gulp = require('gulp-runtime').create();
50 |
51 | gulp.task('read src', function (callback, src, dest) {
52 | dest = path.join(dest, new Date().toISOString());
53 | console.log('from', src, 'to', dest);
54 |
55 | var stream = gulp.src(src);
56 |
57 | callback(null, stream, dest);
58 | });
59 |
60 | gulp.task('write', function (done, stream, dest) {
61 | return stream.pipe(gulp.dest(dest));
62 | });
63 |
64 | // the default takes any arguments after '--' from the terminal
65 | gulp.task('default',
66 | gulp.series('read src', 'write')
67 | );
68 | ```
69 |
70 | write
71 |
72 | ```js
73 | node gulplfile.js -- src/**/*.js build
74 | ```
75 |
76 | and arguments after `--` will be passed to the `default` task.
77 |
78 | #### functions as tasks
79 |
80 | Just as gulp#4.0
81 |
82 | ```js
83 | var gulp = require('gulp-runtime').create();
84 |
85 | function build (done, src, dest) {
86 | console.log('from', src, 'to', dest);
87 | return gulp.src(src)
88 | // some build step
89 | .pipe(gulp.dest(dest));
90 | }
91 |
92 | function minify (done, src, dest) {
93 | return gulp.src(src)
94 | // minify
95 | .pipe(gulp.dest(dest));
96 | }
97 |
98 | gulp.task('default',
99 | gulp.series(build, minify)
100 | );
101 | ```
102 |
103 | #### split builds in instances
104 |
105 | ```js
106 | var styles = require('gulp-runtime').create();
107 |
108 | styles.task('less', function (done, sources, dest) {
109 | var less = require('gulp-less');
110 | var options = require('./build/options');
111 |
112 | return gulp.src(sources)
113 | .pipe(less(options.less))
114 | .pipe(gulp.dest(dest));
115 | });
116 |
117 | styles.task('default', ['less']);
118 |
119 | exports = module.exports = styles;
120 | ```
121 |
122 | #### a REPL after `default` has finished
123 |
124 | ```js
125 | var gulp = require('gulp-runtime').create({ repl: true });
126 |
127 | gulp.task(':number', function (done) {
128 | setTimeout(done, 100);
129 | });
130 |
131 | gulp.task('default', ['one', 'two']);
132 | ```
133 |
134 | go to the terminal and do
135 |
136 | ```sh
137 | node gulpfile.js
138 | ```
139 |
140 | which will run a REPL with the tasks defined.
141 |
142 | ### install
143 |
144 | With [npm][npm]
145 |
146 | ```sh
147 | npm install --save-dev gulp-runtime
148 | ```
149 |
150 | ### why
151 |
152 | Soon after I started to use `gulp` it came to mind
153 |
154 | > I want a REPL for this
155 |
156 | Mainly because a REPL is the closest to `define and use as you like`. If that was possible then writing task names in this REPL will run them just as doing the same from the command line.
157 |
158 | Then I realized that what I really liked from `gulp` is the way you can bundle and compose async functions and how its this done under the hood. For that I had to try to do it by myself.
159 |
160 | The above has lead to [gulp-repl][gulp-repl], [parth][parth], [runtime][runtime] and finally [gulp-runtime][npm].
161 |
162 | So yeah, it got out of hand :D.
163 |
164 | But well oh well, here we are.
165 |
166 | ### license
167 |
168 | [![License][badge-license]][license]
169 |
170 |
171 |
172 | [npm]: http://npmjs.com/gulp-runtime
173 | [parth]: http://npmjs.com/parth
174 | [license]: http://opensource.org/licenses/MIT
175 | [vinylFs]: http://npmjs.com/vinyl-fs
176 | [runtime]: http://github.com/stringparser/runtime
177 | [gulp-repl]: http://github.com/stringparser/gulp-repl
178 | [travis-build]: http://travis-ci.org/stringparser/gulp-runtime/builds
179 |
180 | [badge-build]: http://img.shields.io/travis/stringparser/gulp-runtime/master.svg?style=flat-square
181 | [badge-version]: http://img.shields.io/npm/v/gulp-runtime.svg?style=flat-square
182 | [badge-license]: http://img.shields.io/npm/l/gulp-runtime.svg?style=flat-square
183 | [badge-downloads]: http://img.shields.io/npm/dm/gulp-runtime.svg?style=flat-square
184 |
--------------------------------------------------------------------------------
/docs/API.md:
--------------------------------------------------------------------------------
1 | [docs](./README.md) -
2 | [API](./API.md) -
3 | [CLI](./CLI.md) -
4 | [REPL](./REPL.md) -
5 | [logging](./logging.md) -
6 | [arguments](./arguments.md)
7 |
8 | # API
9 |
10 | The module has 2 static methods
11 |
12 | [Gulp.create](#gulpcreate) -
13 | [Gulp.createClass](#gulpcreateclass)
14 |
15 | the same [gulp API][gulp-api] methods we know and love
16 |
17 | [gulp.src](#gulptask) -
18 | [gulp.dest](#gulptask) -
19 | [gulp.task](#gulptask) -
20 | [gulp.watch](#gulptask)
21 |
22 | and 3 more to bundle/run tasks
23 |
24 | [gulp.series](#gulpseries) -
25 | [gulp.parallel](#gulpparallel) -
26 | [gulp.stack](#gulpstack)
27 |
28 | ## Static methods
29 |
30 | The module exports a constructor function
31 |
32 | ```js
33 | var Gulp = require('gulp-runtime');
34 | ```
35 |
36 | which has two static methods: `Gulp.create` and `Gulp.createClass`.
37 |
38 | ### Gulp.create
39 |
40 | ```js
41 | function create([Object props])
42 | ```
43 |
44 | `Gulp.create` returns a new instance with the given `props`.
45 |
46 | Defaults are:
47 |
48 | - `props.log = true` task logging is enabled, pass `false` to disable it
49 | - `props.repl = false` the REPL is disabled, pass `true` to enable it
50 | - `props.wait = false` tasks will run in **parallel** by default. Pass `wait: true` to make **series** the default when running tasks
51 |
52 | - `props.onStackEnd` called when a stack has ended, defaults to empty function
53 | - `props.onHandleEnd` called after a task has ended, defaults to empty function
54 | - `props.onHandleStart` called before a task starts, defaults to empty function
55 | - `props.onHandleError` called when a task throws, defaults to empty function
56 |
57 | These callbacks can be overridden in [`gulp.series`](#gulpseries), [`gulp.parallel`](#gulpparallel) and [`gulp.stack`](#gulpstack) passing an object as a last argument.
58 |
59 | ### Gulp.createClass
60 |
61 | ```js
62 | function createClass([Object mixin])
63 | ```
64 |
65 | `Gulp.createClass` returns a new constructor function that inherits from its parent prototype.
66 |
67 | - When `mixin` is given it overrides its parent prototype.
68 | - When `mixin.create` is given it will be used as the instance constructor.
69 |
70 | Example:
71 |
72 | Say we always want to make instances that log and have a REPL.
73 |
74 | ```js
75 | var Gulp = require('gulp-runtime').createClass({
76 | create: function Gulp (props) {
77 | props = props || {};
78 | props.log = props.repl = true;
79 | Gulp.super_.call(this, props);
80 | }
81 | });
82 |
83 | exports = module.exports = Gulp;
84 | ```
85 |
86 |
Instance methods
87 |
88 | ### gulp.task
89 |
90 | `gulp.src`, `gulp.dest`, `gulp.watch` and `gulp.task` behave the same as described in the [`gulp` API documentation][gulp-api].
91 |
92 | In addition task names can use `:parameters` (like expressjs routes) and have `arguments` passed from other task or task runner.
93 |
94 | `:parameters` example:
95 |
96 | ```js
97 | var gulp = require('gulp-runtime').create();
98 |
99 | gulp.task('build:mode', function (done) {
100 | console.log(this.params.mode);
101 | done(); // or do async things
102 | });
103 | ```
104 |
105 | `done` will be always passed as first argument to the task. It should be used if the task does not return a stream, promise or [RxJS][RxJS] observable.
106 |
107 | Tasks parameters can also use regular expressions using parens right after the parameter
108 |
109 | ```js
110 | var gulp = require('gulp-runtime').create();
111 |
112 | gulp.task('build:mode(-dev|-prod)', function (done){
113 | done(); // or do async things
114 | });
115 | ```
116 |
117 | To know more about how this tasks names can be set see [parth][parth].
118 |
119 | `arguments` example:
120 |
121 | ```js
122 | var gulp = require('gulp-runtime').create();
123 |
124 | gulp.task('build', function (done, sources, dest) {
125 | var stream = gulp.src(sources)
126 | // some build steps here
127 |
128 | stream.on('end', function () {
129 | // pass stream to next task
130 | done(stream);
131 | });
132 | });
133 |
134 | gulp.task('minify', function (done, stream) {
135 | return stream
136 | // minify
137 | .pipe(gulp.dest(dest));
138 | });
139 |
140 | gulp.task('build and min', function (done) {
141 | gulp.series('build', 'minify')('src/**/*.js', 'dest/source.min.js', done);
142 | });
143 | ```
144 |
145 | ### gulp.start
146 |
147 | Can be used in two ways
148 |
149 | ```js
150 | function start(tasks...)
151 | ```
152 |
153 | Runs any number of `tasks...` given with the defaults of the instance.
154 |
155 | Each of the `tasks...` can be either a `string` or a `function`.
156 |
157 | Example:
158 |
159 | ```js
160 | var gulp = require('gulp-runtime').create({ wait: true });
161 |
162 | function build(done){
163 | done(); // or do async things
164 | }
165 |
166 | gulp.task('thing', function (done){
167 | setTimeout(done, Math.random()*10);
168 | });
169 |
170 | gulp.start(build, 'thing');
171 | // ^ will run in series since the instance was created with `{wait: true}`
172 | ```
173 |
174 | ```js
175 | function start(Array tasks, args...)
176 | ```
177 |
178 | Same as `start(tasks...)` but passing the `args...` down to each of the tasks run.
179 |
180 | ### gulp.series
181 |
182 | ```js
183 | function series(tasks...[, Object options])
184 | ```
185 |
186 | `series` bundles the given `tasks...` into one async function and returns it. This function will **always** run the `tasks...` in **series**.
187 |
188 | Its sugar on top of [`gulp.stack`][#gulpstack]. See [`gulp.stack`][#gulpstack] for more information about `options`.
189 |
190 | ### gulp.parallel
191 |
192 | ```js
193 | function parallel(tasks...[, Object options])
194 | ```
195 |
196 | `parallel` bundles the given `tasks...` into one async function and returns it. This function will **always** run the `tasks...` in **parallel**.
197 |
198 | Its sugar on top of [`gulp.stack`][#gulpstack]. See [`gulp.stack`][#gulpstack] for more information about `options`.
199 |
200 | ### gulp.stack
201 |
202 | ```js
203 | function stack(tasks...[, Object options])
204 | ```
205 |
206 | `stack` bundles the given `tasks...` into one async function and returns it.
207 |
208 | Each `tasks...` can be either a `string` or a `function`.
209 |
210 | If given, `options` will override the instance `props` for this `stack`.
211 |
212 | ---
213 | [Back to top ↑](#)
214 |
215 |
216 |
217 | [npm]: https://npmjs.com/gulp-runtime
218 | [gulp]: https://github.com/gulpjs/gulp
219 | [RxJs]: https://github.com/Reactive-Extensions/RxJS
220 | [parth]: https://github.com/stringparser/parth
221 | [license]: http://opensource.org/licenses/MIT
222 | [runtime]: https://github.com/stringparser/runtime
223 | [gulp-api]: https://github.com/gulpjs/gulp/blob/master/docs/API.md
224 | [gulp-repl]: https://github.com/stringparser/gulp-repl
225 | [open-a-issue]: https://github.com/stringparser/gulp-runtime/issues/new
226 | [example-gulpfile]: https://github.com/gulpjs/gulp#sample-gulpfilejs
227 |
--------------------------------------------------------------------------------
/docs/CLI.md:
--------------------------------------------------------------------------------
1 | [docs](./README.md) -
2 | [API](./API.md) -
3 | [CLI](./CLI.md) -
4 | [REPL](./REPL.md) -
5 | [logging](./logging.md) -
6 | [arguments](./arguments.md)
7 |
8 | ## CLI
9 |
10 | The initial aim of this project was to be able to run gulp tasks directly from a REPL. But when that was then possible, you would also assumme to be able to run the CLI from the REPL, right?
11 |
12 | For this reason the [gulp cli](https://github.com/gulpjs/gulp/blob/master/docs/CLI.md) commands are set as tasks for each instance. This has turn to be useful to use them directly from other tasks.
13 |
14 | Example:
15 |
16 | ```js
17 | var gulp = require('gulp-runtime').create();
18 |
19 | gulp.task('info', ['--tasks', '--version']);
20 | // other tasks...
21 | gulp.task('default', ['info']);
22 | ```
23 |
24 | ---
25 | [Back to top ↑](#)
26 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # documentation
2 |
3 | - [docs](./README.md)
4 | - [API](./API.md)
5 | - [CLI](./CLI.md)
6 | - [REPL](./REPL.md)
7 | - [logging](./logging.md)
8 | - [arguments](./arguments.md)
9 |
10 | ## setup
11 |
12 | 1. Install `npm install --save-dev gulp-runtime`
13 |
14 | 2. Open a `gulpfile`, or [create one][example-gulpfile], and
15 |
16 | change this line
17 |
18 | ```js
19 | var gulp = require('gulp');
20 | ```
21 |
22 | with
23 |
24 | ```js
25 | var gulp = require('gulp-runtime').create();
26 | ```
27 |
28 | After that run the `gulpfile` with `node` directly from the command line
29 |
30 | ```sh
31 | node gulpfile.js default watch serve
32 | ```
33 |
34 | Thats it! When no arguments are given the `default` task will run instead.
35 |
36 | 3. What about the CLI? Can I just run `gulp-runtime` from the terminal?
37 |
38 | Yes. For this add an alias to your `.bashrc` or `.zshrc`
39 |
40 | ```sh
41 | alias gulp-runtime='node $(find . -name "gulpfile.js" -not -path "./node_modules/*" | head -n1)'
42 | ```
43 |
44 | which will use the first `gulpfile.js` found in the current working directory excluding `node_modules`.
45 |
46 | Right after this open a new terminal tab and write
47 |
48 | `gulp-runtime --tasks default watch serve`
49 |
50 |
51 |
52 | [example-gulpfile]: https://github.com/gulpjs/gulp#sample-gulpfilejs
53 |
--------------------------------------------------------------------------------
/docs/REPL.md:
--------------------------------------------------------------------------------
1 | [docs](./README.md) -
2 | [API](./API.md) -
3 | [CLI](./CLI.md) -
4 | [REPL](./REPL.md) -
5 | [logging](./logging.md) -
6 | [arguments](./arguments.md)
7 |
8 | # REPL
9 |
10 | ```js
11 | var gulp = require('gulp-runtime').create({ repl: true });
12 | ```
13 |
14 | When an instance passes `repl: true` the process running does not exit when all tasks are done. For this case, REPL listening on `stdin`.
15 |
16 | ```sh
17 | $ node gulpfile.js
18 | ```
19 |
20 | press enter and you will see a prompt `>` that will run the tasks defined in the gulpfile
21 |
22 | ```sh
23 | >
24 | > build less compress png
25 | ```
26 |
27 | For more information about how tasks are run see [gulp-repl][gulp-repl].
28 |
29 | ---
30 | [Back to top ↑](#)
31 |
32 |
33 |
34 | [gulp-repl]: https://github.com/stringparser/gulp-repl
35 |
--------------------------------------------------------------------------------
/docs/arguments.md:
--------------------------------------------------------------------------------
1 | [docs](./README.md) -
2 | [API](./API.md) -
3 | [CLI](./CLI.md) -
4 | [REPL](./REPL.md) -
5 | [logging](./logging.md) -
6 | [arguments](./arguments.md)
7 |
8 | # Task arguments
9 |
10 | Any of the task runners ([`gulp.start`](./API.md#gulpstart), [`gulp.series`](./API.md#gulpseries), [`gulp.parallel`](./API.md#gulpparallel) and [`gulp.stack`](./API.md#gulpstack)) can be used to pass arguments down.
11 |
12 | ```js
13 | var gulp = require('gulp-runtime').create();
14 | var args = [1, 2, 3];
15 |
16 | gulp.task(':name', function (done, one, two, three) {
17 | console.log(one, two, three);
18 | done(null, one + two + three);
19 | });
20 |
21 | // with gulp.stack
22 | gulp.stack('taskNameHere')(1, 2, 3, function (error, result) {
23 | if (error) {
24 | console.log('ups, who farted?');
25 | console.log(error.stack);
26 | } else {
27 | console.log('all right, we are done at', result, 'pm today');
28 | }
29 | });
30 |
31 | // with gulp.start
32 | gulp.task('default', function (done) {
33 | gulp.start(['taskNameHere'], 1, 2, 3, {
34 | onStackEnd: function (error, result) {
35 | if (error) {
36 | console.log('ups, who farted?');
37 | console.log(error.stack);
38 | } else {
39 | console.log('all right, we are done at', result, 'pm today');
40 | }
41 | done();
42 | }
43 | })
44 | });
45 | ```
46 |
47 | ---
48 | [Back to top ↑](#)
49 |
--------------------------------------------------------------------------------
/docs/logging.md:
--------------------------------------------------------------------------------
1 | [docs](./README.md) -
2 | [API](./API.md) -
3 | [CLI](./CLI.md) -
4 | [REPL](./REPL.md) -
5 | [logging](./logging.md) -
6 | [arguments](./arguments.md)
7 |
8 | # logging
9 |
10 | All callbacks passed to [`Gulp.create`](./API.md#gulpcreate)
11 |
12 | - `onHandleStart`
13 | - `onHandleError`
14 | - `onHandleEnd`
15 | - `onStackEnd`
16 |
17 | are used to internally to produce logging.
18 |
19 | They can also be overridden at:
20 |
21 | - class level with [`Gulp.createClass`](./API.md#gulpcreateclass)
22 | - bunlde/run level using one of the composers ([`gulp.start`](./API.md#gulpstart), [`gulp.series`](./API.md#gulpseries), [`gulp.parallel`](./API.md#gulpparallel) and [`gulp.stack`](./API.md#gulpstack)).
23 |
24 | Example:
25 |
26 | ```js
27 | var MyGulp = require('gulp-runtime').createCLass({
28 | onHandleEnd: function (task) {
29 | console.log('end', task.label);
30 | },
31 | onHandleStart: function (task) {
32 | console.log('start', task.label);
33 | },
34 | onHandleError: function (error, task, stack) {
35 | console.log('error!', task.label);
36 | throw error;
37 | }
38 | });
39 |
40 | var myGulp = MyGulp.create({
41 | onHandleStart: function (task) {
42 | console.log(task.label, 'ended!');
43 | }
44 | });
45 |
46 | myGulp.task(':name', function (done) {
47 | if (this.params && this.params.name === 'three') {
48 | throw new Error('ups, something broke');
49 | } else {
50 | setTimeout(done, 1000);
51 | }
52 | });
53 |
54 | myGulp.stack('one', 'two', 'three', {
55 | onHandleError: function (error, task, stack) {
56 | console.log(task.label, 'is dead');
57 | console.log(error);
58 | }
59 | })();
60 | ```
61 |
62 | ---
63 | [Back to top ↑](#)
64 |
--------------------------------------------------------------------------------
/examples/cli-as-tasks.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('../.').create();
4 |
5 | gulp.task('default', ['--tasks', '--version']);
6 |
--------------------------------------------------------------------------------
/examples/functions-as-tasks.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('../.').create();
4 |
5 | function build (done, src, dest) {
6 | console.log('from', src, 'to', dest);
7 | return gulp.src(src)
8 | // some build step
9 | .pipe(gulp.dest(dest));
10 | }
11 |
12 | function minify (done, src, dest) {
13 | return gulp.src(src)
14 | // minify
15 | .pipe(gulp.dest(dest));
16 | }
17 |
18 | gulp.task('default',
19 | gulp.series(build, minify)
20 | );
21 |
--------------------------------------------------------------------------------
/examples/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('../.').create({repl: true});
4 |
5 | function rand () {
6 | return Math.floor((1000 - 100) * Math.random());
7 | }
8 |
9 | gulp.task('cssmin', ['autoprefixer'], function (next) {
10 | setTimeout(next, rand());
11 | });
12 |
13 | gulp.task('autoprefixer', function (next) {
14 | setTimeout(next, rand());
15 | });
16 |
17 | gulp.task('less :src :dest', function (next) {
18 | return gulp.src(this.params.src)
19 | .pipe()
20 | setTimeout(next, rand());
21 | });
22 |
23 | gulp.task('less', function (next) {
24 | setTimeout(next, rand());
25 | });
26 |
27 | gulp.task('serve', function (next) {
28 | setTimeout(next, rand());
29 | });
30 |
31 | gulp.task('watch', function (next) {
32 | setTimeout(next, rand());
33 | });
34 |
35 | gulp.task('webpack', function (next) {
36 | setTimeout(next, rand());
37 | });
38 |
39 |
40 | gulp.task('default',
41 | gulp.series(
42 | gulp.parallel('less', 'webpack'),
43 | 'cssmin', 'serve', 'watch'
44 | )
45 | );
46 |
--------------------------------------------------------------------------------
/examples/logging.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MyGulp = require('../.').createClass({
4 | onHandleEnd: function (task) {
5 | console.log('end', task.label);
6 | },
7 | onHandleStart: function (task) {
8 | console.log('start', task.label);
9 | },
10 | onHandleError: function (error, task, stack) {
11 | console.log('from', stack.tree().label);
12 | console.log('error!', task.label);
13 | throw error;
14 | }
15 | });
16 |
17 | var myGulp = MyGulp.create({
18 | onHandleStart: function (task) {
19 | console.log(task.label, 'ended!');
20 | }
21 | });
22 |
23 | myGulp.task(':name', function (done) {
24 | if (this.params && this.params.name === 'three') {
25 | throw new Error('ups, something broke');
26 | } else {
27 | setTimeout(done, 1000);
28 | }
29 | });
30 |
31 | myGulp.stack('one', 'two', 'three', {
32 | onHandleError: function (error, task) {
33 | console.log(task.label, 'is dead');
34 | console.log(error);
35 | }
36 | })();
37 |
--------------------------------------------------------------------------------
/examples/pass-arguments.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('../.').create();
4 | var path = require('path');
5 |
6 | gulp.task('read src', function (callback, src, dest) {
7 | dest = path.join(dest, new Date().toISOString());
8 | console.log('from', src, 'to', dest);
9 | var stream = gulp.src(src);
10 |
11 | callback(null, stream, dest);
12 | });
13 |
14 | gulp.task('write', function (done, stream, dest) {
15 | return stream.pipe(gulp.dest(dest));
16 | });
17 |
18 | // the default can take the arguments after '--' from the terminal
19 | gulp.task('default',
20 | gulp.series('read src', 'write')
21 | );
22 |
--------------------------------------------------------------------------------
/examples/src/file.js:
--------------------------------------------------------------------------------
1 | // hello
2 |
--------------------------------------------------------------------------------
/examples/task-parameters.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('../.').create();
4 |
5 | gulp.task('build :src :dest', function () {
6 | return gulp.src(this.params.src)
7 | // transform, compress, etc.
8 | .pipe(gulp.dest(this.params.dest));
9 | });
10 |
11 | gulp.task('default',
12 | gulp.parallel('build src/**/*.js build')
13 | );
14 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var __slice = Array.prototype.slice;
4 |
5 | var Parth = require('parth');
6 | var Runtime = require('runtime');
7 | var vinylFS = require('vinyl-fs');
8 | var globWatch = require('glob-watcher');
9 |
10 | var util = require('./lib/util');
11 | var gulpCLI = require('./lib/cli');
12 |
13 | var Gulp = module.exports = Runtime.createClass({
14 | src: vinylFS.src,
15 | dest: vinylFS.dest,
16 | create: function Gulp (props) {
17 | Gulp.super_.call(this, props);
18 | this.tasks = new Parth({defaultRE: /\S+/});
19 |
20 | this.log = this.props.log === void 0 || this.props.log;
21 | this.gulpfile = util.getGulpFile();
22 |
23 | if (this.log) {
24 | util.log('Using gulpfile', util.format.path(this.gulpfile));
25 | }
26 |
27 | if (this.props.repl) {
28 | this.repl = Gulp.repl.start(this);
29 | }
30 |
31 | // adds the CLI for this instance and runs it for this
32 | gulpCLI(this);
33 | }
34 | });
35 |
36 | /**
37 | * static methods
38 | **/
39 |
40 | Gulp.repl = require('gulp-repl');
41 |
42 | /**
43 | * instance methods
44 | **/
45 |
46 | // gulp.task
47 | Gulp.prototype.task = function (name, deps, handle) {
48 | handle = util.type(handle || deps || name).function || '';
49 | deps = util.type(deps).array || util.type(name).array;
50 | name = util.type(name).string || util.type(handle.name).string;
51 |
52 | if (name && !deps && !handle) {
53 | return (this.tasks.get(name) || {fn: null}).fn;
54 | }
55 |
56 | if (handle && handle.name !== name) {
57 | handle.displayName = name;
58 | }
59 |
60 | if (name && deps && handle) {
61 | var tasks = deps.concat(handle);
62 | var composer = this.series.apply(this, tasks);
63 | this.tasks.set(name, { name: name, fn: composer });
64 | } else if (name && deps) {
65 | var composer = this.stack.apply(this, deps);
66 | this.tasks.set(name, { name: name, fn: composer });
67 | } else if (name) {
68 | this.tasks.set(name, { name: name, fn: handle });
69 | }
70 |
71 | return this;
72 | };
73 |
74 | // gulp.watch
75 | Gulp.prototype.watch = function (glob, opt, fn) {
76 | var tasks = util.type(opt).array;
77 | var handle = util.type(fn || opt).function;
78 |
79 | if (tasks) {
80 | var composer = this.stack.apply(this, tasks);
81 | return globWatch(glob, function (/* arguments */) {
82 | var args = __slice.call(arguments);
83 | composer.apply(null, handle ? args.concat(handle) : args);
84 | });
85 | }
86 |
87 | return globWatch(glob, opt, fn);
88 | };
89 |
90 | // gulp.tree
91 | Gulp.prototype.tree = function (stack, options) {
92 | options = options || {};
93 |
94 | var self = this;
95 | var tasks = null;
96 |
97 | if (Array.isArray(stack)) {
98 | tasks = util.merge([], { props: stack.props });
99 |
100 | for (var i = 0, l = stack.length; i < l; ++i) {
101 | tasks = this.reduceStack(tasks, stack[i], i, stack);
102 | }
103 |
104 | } else {
105 |
106 | tasks = Object.keys(this.tasks.store).filter(function (task) {
107 | return !/^\:cli/.test(task);
108 | }).map(function (name) {
109 | return self.tasks.store[name];
110 | });
111 |
112 | if (options.simple) { return tasks; }
113 | }
114 |
115 | var tree = {label: options.label || '', nodes: []};
116 | var depth = options.depth === void 0 || options.depth;
117 | if (depth && typeof depth !== 'number') { depth = 1; }
118 |
119 | tasks.forEach(function (task) {
120 | if (!task || !task.fn) { return; }
121 | var node;
122 |
123 | if (Array.isArray(task.fn.stack)) {
124 | node = self.tree(task.fn.stack, {
125 | host: task,
126 | depth: depth && (depth + 1) || false
127 | });
128 | } else {
129 | node = {
130 | label: depth == 1 && (task.match || task.name) || task.name
131 | };
132 | }
133 |
134 | tree.label += (tree.label && ', ' + node.label) || node.label;
135 | tree.nodes.push(node);
136 | });
137 |
138 | return tree;
139 | };
140 |
141 | // override of runtime.reduceStack
142 | // maps all the arguments for the gulp.stack to functions
143 |
144 | Gulp.prototype.reduceStack = function (stack, site) {
145 | var task = null;
146 |
147 | if (site && typeof (site.fn || site) === 'function') {
148 | task = site.fn && util.clone(site, true) || {
149 | fn: site,
150 | name: site.displayName || site.name
151 | };
152 | } else {
153 | task = this.tasks.get(site);
154 | }
155 |
156 | if (!task) {
157 | util.log('Task `%s` is not defined yet', util.format.task(site));
158 | util.log('Not sure how to do that? See %s', util.docs.task);
159 |
160 | if (util.isFromCLI(this)) {
161 | process.exit(1);
162 | } else {
163 | throw new Error('task not found');
164 | }
165 | }
166 |
167 | stack.push(task);
168 |
169 | if (Array.isArray(task.fn.stack)) {
170 | task.label = task.name || this.tree(task.fn.stack).label;
171 | } else {
172 | task.label = task.match || task.name;
173 | }
174 |
175 | return stack;
176 | };
177 |
178 |
179 | /**
180 | * tasks logging
181 | **/
182 |
183 | Gulp.prototype.onHandleStart = function (task, stack) {
184 | if (!this.log || (task.params && task.params.cli)) {
185 | return;
186 | }
187 |
188 | if (!stack.time) {
189 | stack.time = process.hrtime();
190 | stack.label = this.tree(stack).label;
191 |
192 | if (Array.isArray(task.fn && task.fn.stack) && task.fn.stack.props) {
193 | stack.match = task.match || task.name || task.displayName;
194 | stack.siteProps = task.fn.stack.props;
195 | }
196 |
197 | util.log('Start', util.format.task(stack));
198 | }
199 |
200 | task.time = process.hrtime();
201 | };
202 |
203 | Gulp.prototype.onHandleEnd = function (task, stack) {
204 | if (this.log && !(task.params && task.params.cli)) {
205 |
206 | if (!(task.fn && Array.isArray(task.fn.stack)) && task.label) {
207 | util.log(' %s took %s',
208 | util.format.task(task),
209 | util.format.time(task.time)
210 | );
211 | } else if (stack.end) {
212 | util.log('Ended %s after %s',
213 | util.format.task(stack),
214 | util.format.time(stack.time)
215 | );
216 | }
217 | }
218 | };
219 |
220 | /**
221 | * error handling
222 | **/
223 |
224 | Gulp.prototype.onHandleError = function (error, site, stack) {
225 | util.log('%s threw an error after %s',
226 | util.format.error(site && site.label || this.tree(stack).label),
227 | util.format.time(site.time)
228 | );
229 |
230 | util.log(error.stack);
231 | };
232 |
233 | /**
234 | * With some sugar on top please
235 | **/
236 |
237 | Gulp.prototype.start = function (/* arguments */) {
238 | var args = null;
239 | var tasks = arguments;
240 |
241 | if (util.type(arguments[0]).array) {
242 | args = __slice.call(arguments, 1);
243 | tasks = arguments[0];
244 | }
245 |
246 | var composer = this.stack.apply(this, tasks.length ? tasks : ['default']);
247 | return composer.apply(this, args);
248 | };
249 |
250 | Gulp.prototype.series = function (/* arguments */) {
251 | var args = __slice.call(arguments);
252 | var props = util.type(args[args.length - 1]).plainObject && args.pop() || {};
253 | var tasks = args.concat(util.merge(props, {wait: true}));
254 | return this.stack.apply(this, tasks);
255 | };
256 |
257 | Gulp.prototype.parallel = function (/* arguments */) {
258 | var args = __slice.call(arguments);
259 | var props = util.type(args[args.length - 1]).plainObject && args.pop() || {};
260 | var tasks = args.concat(util.merge(props, {wait: false}));
261 | return this.stack.apply(this, tasks);
262 | };
263 |
--------------------------------------------------------------------------------
/lib/cli.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var util = require('./util');
4 | var path = require('path');
5 |
6 | var argv = process.argv.slice(2);
7 |
8 | exports = module.exports = function (gulp) {
9 |
10 | gulp.task(':cli(--silent)', function (next) {
11 | gulp.log = false;
12 | util.log = util.gutil.log = util.silent;
13 | next();
14 | });
15 |
16 | gulp.task(':cli(--version|-v)', function (next) {
17 | util.log('gulp-runtime version', require('../package.json').version);
18 | next();
19 | });
20 |
21 | gulp.task(':cli(--cwd) :dirname(\\S+)', function (next) {
22 | var dirname = path.resolve(this.params.dirname);
23 | if (process.cwd() !== dirname) {
24 | process.chdir(dirname);
25 | util.log('cwd changed to', util.format.path(dirname));
26 | }
27 | next();
28 | });
29 |
30 | gulp.task(':cli(--no-color|--color)', function (next) {
31 | util.chalk.enabled = Boolean(this.params.cli === '--color');
32 | if (util.chalk.enabled) {
33 | util.log('colors', util.chalk.green('enabled'));
34 | }
35 | next();
36 | });
37 |
38 | gulp.task(':cli(--tasks-simple|--tasks|-T)', function (next) {
39 | var taskTree = gulp.tree({
40 | label: 'Tasks for ' + util.format.path(gulp.gulpfile),
41 | simple: this.params.cli === '--tasks-simple'
42 | });
43 |
44 | if (this.params.cli === '--tasks-simple') {
45 | console.log(taskTree.join('\n'));
46 | } else if (gulp.log) {
47 | util.archy(taskTree).trim().split('\n').map(function (line) {
48 | util.log(line);
49 | });
50 | }
51 |
52 | next();
53 | });
54 |
55 | gulp.task(':cli(--require) :file(\\S+)', function (next) {
56 | var filename = path.resolve(this.params.file);
57 | util.log('loading', util.format.path(filename));
58 |
59 | try {
60 | var filename = require.resolve(filename);
61 |
62 | if (require.cache[filename]) {
63 | delete require.cache[filename];
64 | }
65 |
66 | require(filename);
67 | } catch (err) {
68 | console.log(util.format.error(err.message));
69 | }
70 |
71 | next();
72 | });
73 |
74 | // skip running tasks if the file was not run from the CLI
75 | if (!util.isFromCLI(gulp)) {
76 | return;
77 | }
78 |
79 | // give some time to have all tasks defined
80 | process.nextTick(function () {
81 | var dirname = path.dirname(gulp.gulpfile);
82 |
83 | // change CWD to the gulpfile's if applies
84 | if (!/(^|[\s])(--cwd)/.test(argv.join(' ')) && process.cwd() !== dirname) {
85 | process.chdir(dirname);
86 | util.log('cwd changed to', util.format.path(dirname));
87 | }
88 |
89 | var args = [];
90 | var index = argv.indexOf('--');
91 |
92 | if (index > -1) {
93 | args = argv.slice(index + 1);
94 | argv = argv.slice(0, index);
95 | }
96 |
97 | if (gulp.repl) {
98 | gulp.repl.emit('line', argv.length ? argv.join(' ') : 'default');
99 | } else {
100 | gulp.start.apply(gulp, [argv].concat(args));
101 | }
102 | });
103 | };
104 |
--------------------------------------------------------------------------------
/lib/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var path = require('path');
4 |
5 | var util = exports = module.exports = {};
6 |
7 | // dependencies
8 | util.type = require('utils-type');
9 | util.clone = require('lodash.clone');
10 | util.archy = require('archy');
11 | util.merge = require('lodash.merge');
12 | util.gutil = require('gulp-util');
13 | util.chalk = util.gutil.colors;
14 | util.tildify = require('tildify');
15 | util.dateFormat = require('dateformat');
16 | util.prettyTime = require('pretty-hrtime');
17 |
18 | // refs
19 | var xargs = process.argv.slice(2).join(' ');
20 | var isSilent = /(^|[\s])(--silent|--tasks-simple)/.test(xargs);
21 | var execFile = path.extname(process.argv[1])
22 | ? process.argv[1]
23 | : process.argv[1] + '.js';
24 |
25 | // assorted
26 | util.docs = {
27 | task: 'http://git.io/vVYKS'
28 | };
29 |
30 | // logging helpers
31 | util.silent = function () {};
32 | util.logger = function (/* arguments */) {
33 | process.stdout.write(util.format.date());
34 | console.log.apply(console, arguments);
35 | };
36 |
37 | // assign the initial logger according to cli args
38 | util.log = util.gutil.log = isSilent ? util.silent : util.logger;
39 |
40 | util.format = {
41 | time: function (hrtime) {
42 | var time = util.prettyTime(process.hrtime(hrtime || []));
43 | return util.chalk.magenta(time);
44 | },
45 | path: function (pahtname) {
46 | return util.chalk.magenta(util.tildify(pahtname));
47 | },
48 | task: function (task) {
49 | if (task && task.label) {
50 | var name = '';
51 | var label = task.label.split(',').map(function (taskName) {
52 | return util.chalk.cyan(taskName);
53 | }).join(',');
54 |
55 | if (task.match && task.siteProps) {
56 | name = task.match + ':' + (task.siteProps.wait ? 'series' : 'parallel');
57 | } else if (task.props) {
58 | name = task.props.wait ? 'parallel' : 'series';
59 | }
60 |
61 | return name ? name + '(' + label + ')' : label;
62 | } else {
63 | return task;
64 | }
65 | },
66 | date: function (date) {
67 | var value = util.dateFormat(date || new Date(), 'HH:MM:ss');
68 | return '[' + util.chalk.grey(value) + '] ';
69 | },
70 | error: function (value) {
71 | return util.chalk.red(value);
72 | }
73 | };
74 |
75 | util.isFromCLI = function (gulp) {
76 | return gulp.gulpfile === execFile;
77 | };
78 |
79 | util.getGulpFile = function () {
80 | var match = new Error().stack.match(/\/([^:()]+)/g);
81 | return match && match[3] || '';
82 | };
83 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gulp-runtime",
3 | "version": "2.0.0",
4 | "description": "an alternate interface to vinly-fs",
5 | "author": "Javier Carrillo Milla",
6 | "engines": {
7 | "node": " >= 0.10"
8 | },
9 | "repository": {
10 | "url": "https://github.com/stringparser/gulp-runtime",
11 | "type": "git"
12 | },
13 | "keywords": [
14 | "gulp",
15 | "repl",
16 | "runtime",
17 | "readline",
18 | "terminal",
19 | "alternate",
20 | "interface"
21 | ],
22 | "dependencies": {
23 | "archy": "^1.0.x",
24 | "chalk": "^1.0.x",
25 | "dateformat": "^1.0.x",
26 | "glob-watcher": "^3.0.x",
27 | "gulp-repl": "^2.0.x",
28 | "gulp-util": "^3.0.x",
29 | "lodash.clone": "^4.5.0",
30 | "lodash.merge": "^4.1.x",
31 | "parth": "^4.2.x",
32 | "pretty-hrtime": "^1.0.x",
33 | "runtime": "^0.14.x",
34 | "tildify": "^1.0.x",
35 | "utils-type": "^0.12.x",
36 | "vinyl-fs": "^2.4.x"
37 | },
38 | "devDependencies": {
39 | "eslint": "^3.3.x",
40 | "mkdirp": "*",
41 | "mocha": "*",
42 | "rimraf": "*",
43 | "should": "*",
44 | "through2": "*"
45 | },
46 | "scripts": {
47 | "lint": "eslint lib examples *.js",
48 | "test": "npm run lint && mocha test"
49 | },
50 | "license": "MIT"
51 | }
52 |
--------------------------------------------------------------------------------
/test/cli.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var path = require('path');
5 | var should = require('should');
6 |
7 | var test = {
8 | file: path.resolve(__dirname, 'dir', 'cliTestFile.js'),
9 | dirname: path.resolve(__dirname, 'dir'),
10 | content: 'exports = module.exports = { test: "cli" };'
11 | };
12 |
13 | exports = module.exports = function (Gulp, util) {
14 |
15 | before(function (done) {
16 | util.mkdirp(test.dirname, function (error) {
17 | if (error) { return done(error); }
18 | fs.writeFile(test.file, test.content, done);
19 | });
20 | });
21 |
22 | after(function (done) {
23 | util.rimraf(test.dirname, done);
24 | });
25 |
26 | it('--silent should turn off logging', function (done) {
27 | var gulp = Gulp.create();
28 |
29 | gulp.log.should.be.eql(true);
30 |
31 | gulp.start(['--silent'], function (error) {
32 | if (error) { return done(error); }
33 | should(gulp.log).be.eql(false);
34 | done();
35 | });
36 | });
37 |
38 | it('--no-color should turn colors off', function (done) {
39 | var gulp = Gulp.create();
40 |
41 | gulp.start(['--no-color'], function (error) {
42 | if (error) { return done(error); }
43 | should(util.lib.chalk).have.property('enabled', false);
44 | done();
45 | });
46 | });
47 |
48 | it('--color should restore them', function (done) {
49 | var gulp = Gulp.create();
50 |
51 | gulp.start(['--color'], function (error) {
52 | if (error) { return done(error); }
53 | should(util.lib.chalk).have.property('enabled', true);
54 | done();
55 | });
56 | });
57 |
58 | it('--cwd :dirname should change cwd', function (done) {
59 | var cwd = process.cwd();
60 | var gulp = Gulp.create();
61 |
62 | gulp.start(['--cwd ' + test.dirname], function (error) {
63 | if (error) { return done(error); }
64 | should(process.cwd()).be.eql(test.dirname);
65 | process.chdir(cwd); // restore previous working directory
66 | done();
67 | });
68 | });
69 |
70 | it('--require should require a module from the cwd', function (done) {
71 | var cwd = process.cwd();
72 | var gulp = Gulp.create();
73 |
74 | should(require.cache).not.have.property(test.file);
75 |
76 | gulp.start(['--require ' + test.file], function (error) {
77 | if (error) { return done(error); }
78 | should(require.cache).have.property(test.file);
79 | process.cwd().should.be.eql(cwd);
80 | done();
81 | });
82 | });
83 | };
84 |
--------------------------------------------------------------------------------
/test/create.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | exports = module.exports = function (Gulp) {
4 | it('create() should log by default', function () {
5 | var gulp = Gulp.create();
6 | gulp.log.should.be.eql(true);
7 | });
8 |
9 | it('create() should have no repl by default', function () {
10 | var gulp = Gulp.create();
11 | gulp.should.not.have.property('repl');
12 | });
13 |
14 | it('create({log: false}) should disable logging', function () {
15 | var gulp = Gulp.create({log: false});
16 | gulp.props.log.should.be.eql(false);
17 | gulp.log.should.be.eql(false);
18 | });
19 |
20 | it('create({repl: true}) should make a repl at gulp.repl', function () {
21 | var gulp = Gulp.create({repl: true});
22 | var readline = require('readline');
23 | gulp.should.have.property('repl');
24 | gulp.repl.should.be.instanceof(readline.Interface);
25 | gulp.repl.close();
26 | });
27 | };
28 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | require('should');
4 |
5 | var Gulp = require('../');
6 | var util = require('./util');
7 |
8 | util.lib.log = function () {
9 | // disable logging for tests
10 | };
11 |
12 | var tests = [
13 | 'create.js',
14 | 'task.js',
15 | 'cli.js',
16 | 'watch.js'
17 | ];
18 |
19 | describe(require('../package').name, function () {
20 | var path = require('path');
21 |
22 | tests.forEach(function (file) {
23 | var suite = path.basename(file, path.extname(file));
24 | describe(suite, function () {
25 | require('./' + file)(Gulp, util);
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/test/task.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | exports = module.exports = function (Gulp) {
4 | var should = require('should');
5 |
6 | it('task(name, fn) registers task `name`', function () {
7 | var gulp = Gulp.create();
8 | var handle = function () {};
9 | gulp.task('name', handle);
10 | gulp.tasks.get('name').fn.should.be.eql(handle);
11 | });
12 |
13 | it('task([Function: name]) registers task `name`', function () {
14 | var gulp = Gulp.create();
15 | function name () {}
16 | gulp.task(name);
17 | gulp.tasks.get('name').fn.should.be.eql(name);
18 | });
19 |
20 | it('task(name, [Function]) registers task `name`', function () {
21 | var gulp = Gulp.create();
22 | function name () {}
23 | gulp.task('taskName', name);
24 | gulp.tasks.get('taskName').fn.should.be.eql(name);
25 | });
26 |
27 | it('task(name) returns task\'s function', function () {
28 | var gulp = Gulp.create();
29 | function name () {}
30 | gulp.task('taskName', name);
31 | gulp.task('taskName').should.be.eql(name);
32 | });
33 |
34 | it('task(name, deps, fn) deps can be defined after', function (done) {
35 | var gulp = Gulp.create();
36 | var deps = ['1', '2', '3'];
37 |
38 | gulp.task('taskName', deps, function () {});
39 | deps.forEach(function (dep) {
40 | (gulp.tasks.get(dep) === null).should.be.eql(true);
41 | });
42 |
43 | function one () {}
44 | gulp.task('1', one);
45 | gulp.task('1').should.be.eql(one);
46 |
47 | done();
48 | });
49 |
50 | it('task(name, deps, fn) non defined deps throw at runtime', function (done) {
51 | var gulp = Gulp.create({log: false});
52 | var deps = ['1', '2', '3'];
53 |
54 | gulp.task('taskName', deps, function () {});
55 | gulp.stack('taskName')(function (error) {
56 | should(error).be.instanceof(Error);
57 | done();
58 | });
59 | });
60 |
61 | it('task(name, deps, fn) deps will run before task', function (done) {
62 | var gulp = Gulp.create({log: false});
63 |
64 | gulp.task('task', ['one', 'two'], function (next, pile) {
65 | pile.push('task');
66 | next(null, pile);
67 | });
68 |
69 | gulp.task('one', function (next, pile) {
70 | pile.push('one');
71 | next(null, pile);
72 | });
73 |
74 | gulp.task('two', function (next, pile) {
75 | pile.push('two');
76 | next(null, pile);
77 | });
78 |
79 | var task = gulp.tasks.get('task');
80 |
81 | task.fn([], function (err, pile) {
82 | if (err) { return done(err); }
83 | pile.should.containDeep(['one', 'two', 'task']);
84 | pile.pop().should.be.eql('task');
85 | done();
86 | });
87 | });
88 |
89 | it('task(name, deps) bundles deps into task `name`', function (done) {
90 | var gulp = Gulp.create({ log: false });
91 |
92 | gulp.task('task', ['one', 'two']);
93 |
94 | gulp.task('one', function (next, pile) {
95 | pile.push('one');
96 | next(null, pile);
97 | });
98 |
99 | gulp.task('two', function (next, pile) {
100 | pile.push('two');
101 | next(null, pile);
102 | });
103 |
104 | var task = gulp.tasks.get('task');
105 |
106 | task.fn([], function (err, pile) {
107 | if (err) { return done(err); }
108 | pile.should.be.eql(['one', 'two']);
109 | done();
110 | });
111 | });
112 | };
113 |
--------------------------------------------------------------------------------
/test/util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | lib: require('../lib/util'),
5 | mkdirp: require('mkdirp'),
6 | rimraf: require('rimraf'),
7 | through: require('through2')
8 | };
9 |
--------------------------------------------------------------------------------
/test/watch.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs');
4 | var path = require('path');
5 |
6 | var test = {
7 | file: path.resolve(__dirname, 'dir', 'watchTestFile.js'),
8 | content: 'exports = module.exports = { test: "watchTest" };',
9 | dirname: path.resolve(__dirname, 'dir')
10 | };
11 |
12 | exports = module.exports = function (Gulp, util) {
13 |
14 | before(function (done) {
15 | util.mkdirp(test.dirname, done);
16 | });
17 |
18 | after(function (done) {
19 | util.rimraf(test.dirname, done);
20 | });
21 |
22 | function setupTest (onSuccess, onError) {
23 | fs.writeFile(test.file, test.content, function (writeError) {
24 | if (writeError) {
25 | return onError(writeError);
26 | }
27 |
28 | onSuccess();
29 |
30 | setTimeout(function () {
31 | fs.writeFile(test.file, '// changed', onError);
32 | }, 10);
33 | });
34 | }
35 |
36 | it('watch(glob, [Function]) should call function on change', function (done) {
37 | var gulp = Gulp.create({log: false});
38 |
39 | setupTest(function () {
40 | var watcher = gulp.watch(test.file, function () {
41 | watcher.end();
42 | done();
43 | });
44 | }, done);
45 | });
46 |
47 | it('watch(glob, tasks) runs tasks in parallel after change', function (done) {
48 | var pile = [];
49 | var gulp = Gulp.create({
50 | log: false,
51 | onHandleError: done
52 | });
53 |
54 | gulp.task('one', function (next) {
55 | setTimeout(function () {
56 | pile.push('one');
57 | if (pile.length > 1) {
58 | pile.should.containDeep(['one', 'two']);
59 | done();
60 | }
61 | next();
62 | }, Math.random() * 10);
63 | });
64 |
65 | gulp.task('two', function (next) {
66 | setTimeout(function () {
67 | pile.push('two');
68 | if (pile.length > 1) {
69 | pile.should.containDeep(['one', 'two']);
70 | done();
71 | }
72 | next();
73 | }, Math.random() * 10);
74 | });
75 |
76 | setupTest(function () {
77 | var watcher = gulp.watch(test.file, ['one', 'two'], function () {
78 | watcher.end();
79 | });
80 | }, done);
81 | });
82 |
83 | it('watch(glob, tasks, fn) onChange fn runs after tasks', function (done) {
84 | var pile = [];
85 | var gulp = Gulp.create({
86 | log: false,
87 | onHandleError: done
88 | });
89 |
90 | gulp.task('one', function (next) {
91 | setTimeout(function () {
92 | pile.push('one');
93 | next();
94 | }, Math.random() * 10);
95 | });
96 |
97 | gulp.task('two', function (next) {
98 | setTimeout(function () {
99 | pile.push('two');
100 | next();
101 | }, Math.random() * 10);
102 | });
103 |
104 | setupTest(function () {
105 | var watcher = gulp.watch(test.file, ['one', 'two'], function () {
106 | pile.should.containDeep(['one', 'two']);
107 | watcher.end();
108 | done();
109 | });
110 | }, done);
111 | });
112 | };
113 |
--------------------------------------------------------------------------------