1 | # taskr [![npm](https://img.shields.io/npm/v/taskr.svg)](https://npmjs.org/package/taskr)
|
2 |
|
3 | Taskr is a highly performant task automation tool, much like Gulp or Grunt, but written with concurrency in mind. With Taskr, everything is a [coroutine](https://medium.com/@tjholowaychuk/callbacks-vs-coroutines-174f1fe66127#.vpryf5tyb), which allows for cascading and composable tasks; but unlike Gulp, it's not limited to the stream metaphor.
|
4 |
|
5 | Taskr is extremely extensible, so _anything_ can be a task. Our core system will accept whatever you throw at it, resulting in a modular system of reusable plugins and tasks, connected by a declarative `taskfile.js` that's easy to read.
|
6 |
|
7 | <h2>Table of Contents</h2>
|
8 |
|
9 | <details>
|
10 | <summary>Table of Contents</summary>
|
11 |
|
12 | - [Features](#features)
|
13 | - [Example](#example)
|
14 | - [Concepts](#concepts)
|
15 | * [Core](#core)
|
16 | * [Plugins](#plugins)
|
17 | * [Tasks](#tasks)
|
18 | * [Taskfiles](#taskfiles)
|
19 | - [CLI](#cli)
|
20 | - [API](#api)
|
21 | * [Taskr](#taskr-1)
|
22 | * [Plugin](#plugin)
|
23 | * [Task](#task-1)
|
24 | * [Utilities](#utilities)
|
25 | - [Installation](#installation)
|
26 | - [Usage](#usage)
|
27 | * [Getting Started](#getting-started)
|
28 | * [Programmatic](#programmatic)
|
29 | - [Credits](#credits)
|
30 | </details>
|
31 |
|
32 | ## Features
|
33 |
|
34 | - **lightweight:** with `6` dependencies, [installation](#installation) takes seconds
|
35 | - **minimal API:** Taskr only exposes a couple methods, but they're everything you'll ever need
|
36 | - **performant:** because of [Bluebird](https://github.com/petkaantonov/bluebird/), creating and running Tasks are quick and inexpensive
|
37 | - **cascading:** sequential Task chains can cascade their return values, becoming the next Task's argument
|
38 | - **asynchronous:** concurrent Task chains run without side effects & can be `yield`ed consistently
|
39 | - **composable:** chain APIs and Tasks directly; say goodbye to `pipe()` x 100!
|
40 | - **modular:** easily share or export individual Tasks or Plugins for later use
|
41 | - **stable:** requires Node `>= 4.6` to run (LTS is `6.11`)
|
42 |
|
43 | ## Example
|
44 |
|
45 | Here's a simple [`taskfile`](#taskfiles) (with [shorthand generator methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions#Shorthand_generator_methods)) depicting a [parallel](#taskrparalleltasks-options) chain.
|
46 |
|
47 | ```js
|
48 | const sass = 'src/{admin,client}/*.sass';
|
49 | const js = 'src/{admin,client}/*.js';
|
50 | const dist = 'build';
|
51 |
|
52 | module.exports = {
|
53 | *lint(task) {
|
54 | yield task.source(js).xo({ esnext:true });
|
55 | },
|
56 | *scripts(task) {
|
57 | yield task.source(js).babel({ presets:['es2015'] }).target(`${dist}/js`);
|
58 | },
|
59 | *styles(task) {
|
60 | yield task.source(sass).sass({ outputStyle:'compressed' }).autoprefixer().target(`${dist}/css`);
|
61 | },
|
62 | *build(task) {
|
63 | yield task.parallel(['lint', 'scripts', 'styles']);
|
64 | }
|
65 | }
|
66 | ```
|
67 |
|
68 | ## Concepts
|
69 |
|
70 | ### Core
|
71 |
|
72 | Taskr is a task runner. It's designed to get you from `A` to `B` -- that's it.
|
73 |
|
74 | If it helps, imagine you're dining in a restaurant and Taskr is the food runner. Taskr's role is solely to collect meals from the kitchen (`task.source`) and deliver them to the correct table (`task.target`). As a food runner, Taskr may do this one plate at a time (`task.serial`) or deliver multiple plates at once (`task.parallel`). Either way, Taskr only cares about going from `A` to `B`. It may not be the most glamorous job, but as far as you (the patron) are concerned, it's incredibly important because it brings you food.
|
75 |
|
76 | ### Plugins
|
77 |
|
78 | Because Taskr is single-minded and cares only about executing [tasks](#tasks), **everything else is a plugin**. This keeps development with Taskr easy, approachable, and lightweight.
|
79 |
|
80 | You see, installing Taskr gives access to a reliable task runner. You decide what it _can do_, provide it functionality, and dictate when to do it. You're in full control.
|
81 |
|
82 | Through plugins, you are able to capture useful behavior and share them across tasks or projects for repeated use. Plugins come in three flavors:
|
83 |
|
84 | * **external** - installed via NPM; called "external" because they live outside your codebase
|
85 | * **inline** - generally simple, one-time functions; not sensible for reuse since declared within a task (hence "inline")
|
86 | * **local** - private, reusable plugins; appear exactly like external plugins but not public on NPM.
|
87 |
|
88 | ### Tasks
|
89 |
|
90 | Tasks are used to tell Taskr what to do. They are written as generator functions & converted to coroutines internally. They're also fully self-contained and, like plugins, can be shared across projects if desired.
|
91 |
|
92 | Upon runtime, tasks are cheap to create, so are also destroyed once completed. This also helps Taskr remain efficient; history won't weigh it down.
|
93 |
|
94 | Lastly, tasks have the power to [start](#taskstarttask-options) other Tasks, including [serial](#taskserialtasks-options) and [parallel](#taskparalleltasks-options) chains!
|
95 |
|
96 | ### Taskfiles
|
97 |
|
98 | Much like Gulp, Taskr uses a `taskfile.js` (case sensitive) to read and run your Tasks. However, because it's a regular JavaScript file, you may also `require()` additional modules and incorporate them directly into your Tasks, without the need for a custom Plugin!
|
99 |
|
100 | ```js
|
101 | const browserSync = require('browser-sync');
|
102 |
|
103 | exports.serve = function * (task) {
|
104 | browserSync({
|
105 | port: 3000,
|
106 | server: 'dist',
|
107 | middleware: [
|
108 | require('connect-history-api-fallback')()
|
109 | ]
|
110 | });
|
111 | yield task.$.log('> Listening on localhost:3000');
|
112 | }
|
113 | ```
|
114 |
|
115 | Taskfiles should generally be placed in the root of your project, alongside your `package.json`. Although this is not required, Taskr (strongly) prefers this location.
|
116 |
|
117 | > **Note:** You may set an alternate directory path through the CLI's `cwd` option.
|
118 |
|
119 | Through Node, Taskr only supports ES5 syntax; however, if you prefer ES6 or ES7, just install [`@taskr/esnext`](https://github.com/lukeed/taskr/tree/master/packages/esnext)!
|
120 |
|
121 | ## CLI
|
122 |
|
123 | Taskr's CLI tool is very simple and straightforward.
|
124 |
|
125 | ```
|
126 | taskr [options] <task names>
|
127 | taskr --mode=parallel task1 task2 ...
|
128 | ```
|
129 | > Please run `taskr --help` or `taskr -h` for usage information.
|
130 |
|
131 | Most commonly, the CLI is used for [NPM script](https://docs.npmjs.com/misc/scripts) definitions.
|
132 |
|
133 | ```js
|
134 | // package.json
|
135 | {
|
136 | "scripts": {
|
137 | "build": "taskr foo bar"
|
138 | }
|
139 | }
|
140 | ```
|
141 |
|
142 | ## API
|
143 |
|
144 | ### Taskr
|
145 |
|
146 | Taskr itself acts as a "parent" class to its `Task` children. Because of this, Taskr's methods are purely executive; aka, they manage Tasks and tell them how & when to run.
|
147 |
|
148 | #### Taskr.start(task, [options])
|
149 | Yield: `Any`<br>
|
150 | Start a Task by its name; may also pass initial values. Can return anything the Task is designed to.
|
151 |
|
152 | ##### task
|
153 | Type: `String`<br>
|
154 | Default: `'default'`<br>
|
155 | The Task's name to run. Task must exist/be defined or an Error is thrown.<br>
|
156 | > **Important!** Taskr expects a `default` task if no task is specified. This also applies to CLI usage.
|
157 |
|
158 | ##### options
|
159 | Type: `Object`<br>
|
160 | Default: `{ src:null, val:null }`<br>
|
161 | Initial/Custom values to start with. You may customize the object shape, but only `val` will be cascaded from Task to Task.
|
162 |
|
163 | #### Taskr.parallel(tasks, [options])
|
164 | Yield: `Any`<br>
|
165 | Run a group of tasks simultaneously. Cascading is disabled.
|
166 | ##### tasks
|
167 | Type: `Array`<br>
|
168 | The names of Tasks to run. Task names must be `string`s and must be defined.
|
169 | ##### options
|
170 | Type: `Object`<br>
|
171 | Initial values to start with; passed to each task in the group. Does not cascade.
|
172 |
|
173 | #### Taskr.serial(tasks, [options])
|
174 | Yield: `Any`<br>
|
175 | Run a group of tasks sequentially. Cascading is enabled.
|
176 | ##### tasks
|
177 | Type: `Array`<br>
|
178 | The names of Tasks to run. Task names must be `string`s and must be defined.
|
179 | ##### options
|
180 | Type: `Object`<br>
|
181 | Initial values to start with; passed to each task in the group. Does cascade.
|
182 |
|
183 | ```js
|
184 | module.exports = {
|
185 | *default(task) {
|
186 | yield task.serial(['first', 'second'], { val:10 });
|
187 | },
|
188 | *first(task, opts) {
|
189 | yield task.$.log(`first: ${opts.val}`);
|
190 | return opts.val * 4;
|
191 | },
|
192 | *second(task, opts) {
|
193 | yield task.$.log(`second: ${opts.val}`);
|
194 | return opts.val + 2;
|
195 | }
|
196 | }
|
197 |
|
198 | const output = yield task.start();
|
199 | //=> first: 10
|
200 | //=> second: 40
|
201 | console.log(output);
|
202 | //=> 42
|
203 | ```
|
204 |
|
205 | ### Plugin
|
206 |
|
207 | Plugins can be external, internal, or local. However, all plugins share the same options:
|
208 |
|
209 | ##### options.every
|
210 | Type: `Boolean`<br>
|
211 | Default: `true`<br>
|
212 | If the plugin function should iterate through _every_ `file|glob`.
|
213 |
|
214 | ##### options.files
|
215 | Type: `Boolean`<br>
|
216 | Default: `true`<br>
|
217 | If the plugin should receive the Task's `glob` patterns or its expanded `file` objects. Uses `globs` if `false`.
|
218 |
|
219 | Every plugin must also pass a **generator function**, which will be wrapped into a coroutine. This function's arguments will be the `file|glob`(s), depending on the `options.every` and `options.files` combination. The function's second argument is the user-provided config object.
|
220 |
|
221 | The plugin's generator function is **always** bound to the current `Task`, which means `this` refers to the Task instance.
|
222 |
|
223 | #### Internal Plugins
|
224 |
|
225 | Internal plugins are for single-use only. If you're defining the same behavior repeatedly, it should be extracted to a local or external plugin instead.
|
226 |
|
227 | > **Note:** Inline plugins have no need for a second argument in their generator function; you are the "user" here.
|
228 |
|
229 | See [`task.run`](#taskrunoptions-generator) for a simple example. The same inline example may be written purely as an object:
|
230 |
|
231 | ```js
|
232 | exports.foo = function * (task) {
|
233 | yield task.source('src/*.js').run({
|
234 | every: false,
|
235 | *func(files) {
|
236 | Array.isArray(files); //=> true
|
237 | yield Promise.resolve('this will run once.');
|
238 | }
|
239 | }).target('dist');
|
240 | }
|
241 | ```
|
242 |
|
243 | #### External Plugins
|
244 |
|
245 | Unlike "inline" plugins, external and local plugins are defined before a Task is performed. Because of this, they must define a `name` for their method to use within a Task.
|
246 |
|
247 | Similar to inline plugins, there are two ways of defining an exported module -- via functional or object definitions.
|
248 |
|
249 | When using a _functional definition_, the **definition** receives the [Taskr](#taskr-1) instance and the [utilities](#utilities) object.
|
250 |
|
251 | ```js
|
252 | module.exports = function (task, utils) {
|
253 | // promisify before running else repeats per execution
|
254 | const render = utils.promisify(function () {});
|
255 | // verbose API
|
256 | task.plugin('myName', {every: false}, function * (files, opts) {
|
257 | console.log('all my files: ', files); //=> Array
|
258 | console.log(this._.files === files); //=> true
|
259 | console.log(this instanceof Task); //=> true
|
260 | console.log('user options: ', opts);
|
261 | yield render(opts);
|
262 | });
|
263 | // or w/condensed API
|
264 | task.plugin({
|
265 | name: 'myName',
|
266 | every: false,
|
267 | *func(files, opts) {
|
268 | // ...same
|
269 | }
|
270 | });
|
271 | }
|
272 | ```
|
273 |
|
274 | When using an _object definition_, you are not provided the `task` or `utils` parameters. **This assumes that you do not need any prep work for your plugin!**
|
275 |
|
276 | ```js
|
277 | module.exports = {
|
278 | name: 'myName',
|
279 | every: false,
|
280 | *func(files, opts) {
|
281 | // do stuff
|
282 | }
|
283 | }
|
284 | ```
|
285 |
|
286 | Then, within your Task, you may use it like so:
|
287 |
|
288 | ```js
|
289 | exports.default = function * (task) {
|
290 | yield task.source('src/*.js').myName({ foo:'bar' }).target('dist');
|
291 | }
|
292 | ```
|
293 |
|
294 | #### Local Plugins
|
295 |
|
296 | Local plugins are defined exactly like external plugins. The only difference is that they're not installable via NPM.
|
297 |
|
298 | In order to use a local plugin, add a `taskr` key to your `package.json` file. Then define a `requires` array with paths to your plugins.
|
299 |
|
300 | ```js
|
301 | {
|
302 | "taskr": {
|
303 | "requires": [
|
304 | "./build/custom-plugin-one.js",
|
305 | "./build/custom-plugin-two.js"
|
306 | ]
|
307 | }
|
308 | }
|
309 | ```
|
310 |
|
311 | For [programmatic usage](#programmatic), simply pass an array of definitions to the `plugins` key:
|
312 |
|
313 | ```js
|
314 | const Taskr = require('taskr')
|
315 | const taskr = new Taskr({
|
316 | plugins: [
|
317 | require('./build/custom-plugin-one.js'),
|
318 | require('./build/custom-plugin-two.js'),
|
319 | require('@taskr/clear')
|
320 | {
|
321 | name: 'plugThree',
|
322 | every: false,
|
323 | files: false,
|
324 | *func(globs, opts) {
|
325 | // nifty, eh?
|
326 | }
|
327 | }
|
328 | ]
|
329 | });
|
330 | ```
|
331 |
|
332 | ### Task
|
333 |
|
334 | A Task receives itself as its first argument. We choose to name the parameter `task` simply as a convention; of course, you may call it whatever you'd like.
|
335 |
|
336 | Tasks are exported from a `taskfile.js`, which means you can use either syntax:
|
337 |
|
338 | ```js
|
339 | exports.foo = function * (task) {
|
340 | yield task.source('src/*.js').target('dist/js');
|
341 | }
|
342 | exports.bar = function * (task) {
|
343 | yield task.source('src/*.css').target('dist/css');
|
344 | }
|
345 | // or
|
346 | module.exports = {
|
347 | *foo(task) {
|
348 | yield task.source('src/*.js').target('dist/js');
|
349 | },
|
350 | *bar(task) {
|
351 | yield task.source('src/*.css').target('dist/css');
|
352 | }
|
353 | }
|
354 | ```
|
355 |
|
356 | Each Task also receives an `opts` object, consisting of `src` and `val` keys. Although `src` is primarily used for [`@taskr/watch`](https://github.com/lukeed/taskr/tree/master/packages/watch), the `val` key can be used or set at any time see [`Taskr.serial`](#taskrserialtasks-options).
|
357 |
|
358 | All methods and values below are exposed within a Task's function.
|
359 |
|
360 | #### task.root
|
361 | Type: `String`<br>
|
362 | The directory wherein `taskfile.js` resides, now considered the root. Also accessible within plugins.
|
363 |
|
364 | #### task.$
|
365 | Type: `Object`<br>
|
366 | The Task's utility helpers. Also accessible within plugins. See [Utilities](#utilities).
|
367 |
|
368 | #### task._
|
369 | Type: `Object`<br>
|
370 | The Task's internal state, populated by `task.source()`. Also accessible within plugins.
|
371 | ##### task._.files
|
372 | Type: `Array`<br>
|
373 | The Task's active files. Each object contains a `dir` and `base` key from its [`pathObject`](https://nodejs.org/api/path.html#path_path_format_pathobject) and maintains the file's Buffer contents as a `data` key.
|
374 | ##### task._.globs
|
375 | Type: `Array`<br>
|
376 | The Task's glob patterns, from `task.source()`. Used to populate `task._.files`.
|
377 | ##### task._.prevs
|
378 | Type: `Array`<br>
|
379 | The Task's last-known (aka, outdated) set of glob patterns. Used **only** for [`@taskr/watch`](https://github.com/lukeed/taskr/tree/master/packages/watch).
|
380 |
|
381 | #### task.source(globs, [options])
|
382 | ##### globs
|
383 | Type: `Array|String`<br>
|
384 | Any valid glob pattern or array of patterns.
|
385 | ##### options
|
386 | Type: `Object`<br>
|
387 | Default: `{}`<br>
|
388 | Additional options, passed directly to [`node-glob`](https://github.com/isaacs/node-glob#options).
|
389 |
|
390 | #### task.target(dirs, [options])
|
391 | ##### dirs
|
392 | Type: `Array|String`<br>
|
393 | The destination folder(s).
|
394 | ##### options
|
395 | Type: `Object`<br>
|
396 | Default: `{}`<br>
|
397 | Additional options, passed directly to [`fs.writeFile`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).
|
398 |
|
399 | Please note that `task.source()` glob ambiguity affects the destination structure.
|
400 |
|
401 | ```js
|
402 | yield task.source('src/*.js').target('dist');
|
403 | //=> dist/foo.js, dist/bar.js
|
404 | yield task.source('src/**/*.js').target('dist');
|
405 | //=> dist/foo.js, dist/bar.js, dist/sub/baz.js, dist/sub/deep/bat.js
|
406 | ```
|
407 |
|
408 | #### task.run(options, generator)
|
409 | Perform an inline plugin.
|
410 |
|
411 | ##### options
|
412 | Type: `Object`<br>
|
413 | The See [plugin options](#plugin).
|
414 | ##### generator
|
415 | Type: `Function`<br>
|
416 | The action to perform; must be a `Generator` function.
|
417 |
|
418 | ```js
|
419 | exports.foo = function * (task) {
|
420 | yield task.source('src/*.js').run({ every:false }, function * (files) {
|
421 | Array.isArray(files); //=> true
|
422 | yield Promise.resolve('this will run once.');
|
423 | }).target('dist')
|
424 | }
|
425 | ```
|
426 |
|
427 | #### task.start(task, [options])
|
428 | See [`Taskr.start`](#taskrstarttask-options).
|
429 |
|
430 | #### task.parallel(tasks, [options])
|
431 | See [`Taskr.parallel`](#taskrparalleltasks-options).
|
432 |
|
433 | #### task.serial(tasks, [options])
|
434 | See [`Taskr.serial`](#taskrserialtasks-options).
|
435 |
|
436 | ### Utilities
|
437 |
|
438 | A collection of utility helpers to make life easy.
|
439 |
|
440 | #### alert(...msg)
|
441 | Print to console with timestamp and alert coloring. See [`utils.log`](#logmsg).
|
442 | ##### msg
|
443 | Type: `String`
|
444 |
|
445 | #### coroutine(generator)
|
446 | See [Bluebird.coroutine](http://bluebirdjs.com/docs/api/promise.coroutine.html).
|
447 |
|
448 | #### error(...msg)
|
449 | Print to console with timestamp and error coloring. See [`utils.log`](#logmsg).
|
450 | ##### msg
|
451 | Type: `String`
|
452 |
|
453 | #### expand(globs, options)
|
454 | Yield: `Array`<br>
|
455 | Get all filepaths that match the glob pattern constraints.
|
456 | ##### globs
|
457 | Type: `Array|String`
|
458 | ##### options
|
459 | Type: `Object`<br>
|
460 | Default: `{}`<br>
|
461 | Additional options, passed directly to [`node-glob`](https://github.com/isaacs/node-glob#options).
|
462 |
|
463 | #### find(filename, dir)
|
464 | Yield: `String|null`<br>
|
465 | Find a complete filepath from a given path, or optional directory.
|
466 | ##### filename
|
467 | Type: `String`<br>
|
468 | The file to file; may also be a complete filepath.
|
469 | ##### dir
|
470 | Type: `String`<br>
|
471 | Default: `'.'`<br>
|
472 | The directory to look within. Will be prepended to the `filename` value.
|
473 |
|
474 | #### log(...msg)
|
475 | Print to console with timestamp and normal coloring.
|
476 | ##### msg
|
477 | Type: `String`<br>
|
478 | You may pass more than one `msg` string.
|
479 |
|
480 | ```js
|
481 | utils.log('Hello');
|
482 | //=> [10:51:04] Hello
|
483 | utils.log('Hello', 'World');
|
484 | //=> [10:51:14] Hello World
|
485 | ```
|
486 |
|
487 | #### promisify(function, callback)
|
488 | See [Bluebird.promisify](http://bluebirdjs.com/docs/api/promise.promisify.html).
|
489 |
|
490 | #### read(filepath, options)
|
491 | Yield: `Buffer|String|null`<br>
|
492 | Get a file's contents. Ignores directory paths.
|
493 | ##### filepath
|
494 | Type: `String`<br>
|
495 | The full filepath to read.
|
496 | ##### options
|
497 | Type: `Object`<br>
|
498 | Additional options, passed to [`fs.readFile`](https://nodejs.org/api/fs.html#fs_fs_readfile_file_options_callback).
|
499 |
|
500 | #### trace(stack)
|
501 | Parse and prettify an Error's stack.
|
502 |
|
503 | #### write(filepath, data, options)
|
504 | Yield: `null`<br>
|
505 | Write given data to a filepath. Will create directories as needed.
|
506 | ##### filepath
|
507 | Type: `String`<br>
|
508 | The full filepath to write into.
|
509 | ##### data
|
510 | Type: `String|Buffer`<br>
|
511 | The data to be written; see [`fs.writeFile`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).
|
512 | ##### options
|
513 | Type: `Object`<br>
|
514 | Additional options, passed to [`fs.writeFile`](https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback).
|
515 |
|
516 | ## Installation
|
517 |
|
518 | ```sh
|
519 | $ npm install --save-dev taskr
|
520 | ```
|
521 |
|
522 | ## Usage
|
523 |
|
524 | ### Getting Started
|
525 |
|
526 | 1. Install Taskr & any desired plugins. (see [installation](#installation) and [ecosystem](https://github.com/lukeed/taskr#packages))
|
527 | 2. Create a `taskfile.js` next to your `package.json`.
|
528 | 3. Define `default` and additional tasks within your `taskfile.js`.
|
529 |
|
530 | ```js
|
531 | exports.default = function * (task) {
|
532 | yield task.parallel(['styles', 'scripts']);
|
533 | }
|
534 |
|
535 | exports.styles = function * (task) {
|
536 | yield task.source('src/**/*.css').autoprefixer().target('dist/css');
|
537 | }
|
538 |
|
539 | exports.scripts = function * (task) {
|
540 | yield task.source('src/**/*.js').babel({
|
541 | presets: [
|
542 | ['es2015', { loose:true, modules:false }]
|
543 | ]
|
544 | }).target('dist/js');
|
545 | }
|
546 | ```
|
547 | 4. Add a `"scripts"` key to your `package.json`:
|
548 |
|
549 | ```json
|
550 | {
|
551 | "name": "my-project",
|
552 | "scripts": {
|
553 | "build": "taskr"
|
554 | }
|
555 | }
|
556 | ```
|
557 |
|
558 | > **Note:** The `default` task is run if no other tasks are specified.
|
559 | 5. Run your `build` command:
|
560 |
|
561 | ```sh
|
562 | $ npm run build
|
563 | ```
|
564 |
|
565 | You may be interested in checking out [Web Starter Kit](https://github.com/lukeed/fly-kit-web) for a head start.
|
566 |
|
567 | ### Programmatic
|
568 |
|
569 | Taskr is extremely flexible should you choose to use Taskr outside of its standard configuration.
|
570 |
|
571 | The quickest path to a valid `Taskr` instance is to send a `tasks` object:
|
572 |
|
573 | ```js
|
574 | const Taskr = require('Taskr');
|
575 | const taskr = new Taskr({
|
576 | tasks: {
|
577 | *foo(f) {},
|
578 | *bar(f) {}
|
579 | }
|
580 | });
|
581 | taskr.start('foo');
|
582 | ```
|
583 |
|
584 | By default, your new Taskr instance will not include any plugins. You have the power to pick and choose what your instance needs!
|
585 |
|
586 | To do this, you may pass an array of [external](#external-plugins) and [local](#local-plugins) `plugins`:
|
587 |
|
588 | ```js
|
589 | const taskr = new Taskr({
|
590 | plugins: [
|
591 | require('@taskr/concat'),
|
592 | require('@taskr/clear'),
|
593 | require('./my-plugin')
|
594 | ]
|
595 | });
|
596 | ```
|
597 |
|
598 | > **Important:** This assumes you have provided a valid `file` _or_ `tasks` object. Without either of these, your Taskr instance will be incomplete and therefore invalid. This will cause the instance to exit early, which means that your `plugins` will not be mounted to the instance.
|
599 |
|
600 | You may also define your `tasks` by supplying a `taskfile.js` path to `file`. Whenever you do this, you **should** also update the `cwd` key because your [root](#taskroot) has changed!
|
601 |
|
602 | ```js
|
603 | const join = require('path').join;
|
604 |
|
605 | const cwd = join(__dirname, '..', 'build');
|
606 | const file = join(cwd, 'taskfile.js');
|
607 |
|
608 | const taskr = new Taskr({ file, cwd });
|
609 | ```
|
610 |
|
611 |
|
612 | ## Credits
|
613 |
|
614 | This project used to be called `fly`, but [Jorge Bucaran](https://github.com/jbucaran), its original author, generously handed over the project to [Luke Edwards](https://github.com/lukeed) in order to further development. The project is now named `taskr` to reflect the transition and its exicitng new future!
|
615 |
|
616 | A **big thanks** to [Constantin Titarenko](https://github.com/titarenko) for donating the name `taskr` on NPM -- very much appreciated!
|