Taskero
Task automation tool with special focus on: asynchronicity, parameterization and automatic watches functionality.
1. Installation
~$ npm install --save taskero
2. Usage
2.1. Example
This is a simple example. It simulates the compilation of JSX files to JS, and then it writes the concatenation of them into a file.
We can specify both, the termination of the files that will contain the compilation, and the file that will contain the concatenation of the compiled files.
The cool thing is that we can reuse the same function, because we parametrize some of the variables of the task, and when we run them, we redefine them.
const Taskero = Taskero;const taskero = debug:false;const compileJSX = { // Here, you can modify the contents of the file return i};const fs = ; taskero; taskero; taskero;
2.2. Step-by-step explanation
The following is a step-by-step explanation of the previous example.
1. Import Taskero class and create an instance:
const Taskero = Taskero;const taskero = debug:false;
The object passed into the constructor sets the options for the instance created.
The only option, for now, is debug
. If set to true
, it will log by console all
the actions that taskero is carrying on under the hood. By default, this option is
set to false
, so this option is redundant, and the object itself is optional too.
2. Register the tasks we want.
taskero;
The object passed to the Taskero#register(~)
method here defines the default
options known by the API. Moreover, you can provide your own properties.
When you provide your own properties here, they will be set as default for the
current task. They, though, will be extendable by the Taskero#run(~)
method.
3. Run the tasks we want, overriding or adding the parameters we want.
taskero;
The Taskero#run(~)
method accepts different types of arguments. The shown below
is the most flexible, as it accepts multiple tasks (that will be run one after
the other) and, at the same time, their parametrization. This way, we can reuse
the same task against different files.
Remember that the watch
option will let you run the task as a watcher, instead
of as a simple execution, just providing a true
flag, which can result very
handy in order to reuse a task in watcher mode.
Note: the watcher mode
means that the files
matched will be listened for
changes, and so, you can forget about running the task: it will be run
automatically for you everytime a file is changed, or created, or removed.
3. API Reference
require("taskero").Taskero
Type: {Class}
.
Description: Returns the main class of the Taskero
's API.
new Taskero(Object:options)
Type: {Class}
.
Property: {Array<Object>} tasksMap
.
Property: {Array<Object>} watchers
.
Property: {Object} options
. By default: {debug:false}
.
Parameter: {Object} options
. Optional. Configurations of the new
instance. By default:
debug: false
Return: {Object}
.
Description: Creates and returns a new Taskero
instance.
Taskero#tasksMap
Type: {Object}
.
Description: Information of all the tasks (identified by their name
)
that have been registered by this Taskero
instance.
Taskero#options
Type: {Object}
Description: Options passed to this Taskero
instance. This is built
by the default options, and the object provided as first argument to
the Taskero
constructor.
Default options:
debug: true
Taskero#watchers
Type: {Array<Object>}
Description: File watchers added by this Taskero
instance.
Taskero#register(Object:taskInfo)
Type: {Function}
Description: Registers a new task for this instance.
Parameter: {Object} taskInfo
. Required
.
The Taskero#register(~)
method accepts an object as parameter.
This object can have any of the following properties:
-
name
:{String}
. Required. The name of the task. It can not be duplicated. Otherwise, an error will be thrown. -
onEach
:{Array<Function> | Function}
. Optional. Functions that compose this task, that will be applied to each file (matched by thefiles
argument). This implies that each of the functions provided by this argument will be applied once per each matched file. By default:[]
.
These functions (or function) will receive 3 parameters:
· argument 1:
done
: {Function}
. This must be called to finish the callback,
and to start the next call. When called with 1 parameter, the {String}
passed
to it will change the content of the file (but not written). When called with 2
parameters, the second parameter will throw an error, catched by the
Taskero#run(...).then(...).catch(~)
callback.
· argument 2:
file
: {Object}
. This object has a .path
and a .contents
property. This object will be passed through all the onEach
callbacks. The
.contents
property can be modified directly, or by the done(~)
call. Take
into account that any matched file will appear here.
· argument 3:
args
: {Object}
. This object has all the parameters received
by this task. So: name
, onEach
, onDone
, onDoneFile
, files
... and any
other parameter added by the method Taskero#register(~)
or the method
Taskero#run(~)
will also appear here.
-
onDone
:{Array<Function> | Function}
. Optional. Functions that compose this task, that will be applied after all theonEach
callbacks are solved. The arguments that it receives are the same as theonEach
callbacks, but as this set of callbacks are going to be called only once (and not once per file, as theonEach
callbacks), the second arguments is notfile
, butfiles
. If their contents were modified byonEach
callbacks, they will remain modified here too. This callback is useful to concatenate the contents of all the files somewhere, or for tasks that are executed once, independently from thefiles
. Also, note that when thedone
call is provided with 1 parameter, it will dump the passed{String}
into the file specified at the parameteronDoneFile
, if any. When it is called with 2, it will throw an error, catched by theTaskero#run(...).then(...).catch(~)
callback. By default:[]
. -
onDoneFile
:{String}
. Optional. File that will be written with the{String}
passed to thedone
(the first argument) of theonDone
parameter. The file and folders, if not already created, will be created. If the saiddone
call is not provided with 1 parameter, it will not dump anything to any file. By default:undefined
. -
files
:{Array<String> | String}
. Optional. Glob pattern(s) that will be matched before proceeding to theonEach
andonDone
callbacks execution. It can be empty, in which case, noonEach
callback will be called (but theonDone
will be called anyway). By default:[]
. -
filesEncoding
:{String}
. Optional. By default:"utf8"
. -
watch
:{Boolean}
. Optional. When set totrue
, the task will be understood as a watcher, not as an executor. This means that the glob patterns will be used to be watched (by chokidar library), instead of matched (by globby library. When set totrue
, the watchers generated will be added intoTaskero#watchers
, which starts as an empty array. And they can be all closed and removed by calling toTaskero#closeWatchers()
, directly. By default:false
. -
watchOptions
:{Object}
. Optional. This object is passed to the chokidar library as thewatch
options. By default:{persist: true}
.
Taskero#run(String:taskName)
Taskero#run(Object:taskParameters)
Taskero#run(Array<Object:taskParameters>:tasks)
Type: {void}
Parameter: {Array<Object>} tasks
. Set of tasks to be run. They will be
executed one after the other. The object will override the one passed to
the registered task (that has the same name). The objects inside this
array, so, are the same as the ones defined in the registration: Taskero
tasks. The parameters added or overriden, are only overriden for the
execution. This lets the user to refer to different files, but take some
default files, for example.
Returns: {Promise}
. To chain the then(~)
and catch(~)
calls.
Description: Runs the provided tasks, in series (one after the other, in a synchronous way).
Taskero#closeWatchers()
Type: {Function}
.
Parameters: {none}
.
Returns: {void}
.
Description: Removes all the Taskero#watchers
added to the instance.
Taskero#debug(Any:message,...)
Type: {Function}
.
Parameters: {Any:message,...}
.
Returns: {void}
.
Description: Logs the provided messages, only if the Taskero#options.debug
is set to true
.
Taskero#error(Any:message,...)
Type: {Function}
.
Parameters: {Any:message,...}
.
Returns: {void}
.
Description: Logs the provided messages, only if the Taskero#options.error
is set to true
(which by default, it is).
Taskero.execute()
Taskero.execute(Array<String>:command)
Taskero.execute(String:command)
Type: {Function}
.
Parameters: {Array<String>:command | String:command | void}
. Commands to execute. It can be
an array of strings (like process.argv
), a normal string (as the input of the command-line)
or nothing at all (in which case, the process.argv
is taken as parameter).
Returns: {void}
.
Description: Executes a specific command, as a normal command-line tool would.
Taskero.transformCommands()
Taskero.transformCommands(Array<String>:command)
Taskero.transformCommands(String:command)
Type: {Function}
.
Parameters: {Array<String>:command | String:command | void}
. Commands to execute. It can be
an array of strings (like process.argv
), a normal string (as the input of the command-line)
or nothing at all (in which case, the process.argv
is taken as parameter).
Returns: {void}
.
Description: Executes a specific command, as a normal command-line tool would.
4. Tests, coverage and documentation
The package.json
file is provided with 3 commands:
-
npm run docs
: it generates the documentation from the Javadoc comments of thesrc/taskero.js
file, which contains the whole library. -
npm run test
: it runs the tests and generates the coverage reports intocoverage/
folder. -
npm run test-nocov
: it runs the tests, but it does not generate coverage reports. Use this command if you want to run tests fastly.
5. Why?
I felt that Grunt is cool, and Gulp is cool, and Webpack is cool.
Yes, they are cool.
But:
- Webpack, which was the coolest, complicated things too much.
(I only need to listen for changes, and do things, I do not want to change the way I code for a task-automation tool! The less, the better: that is programming for me in a 70% of the cases, for lots of reasons.)
- Grunt, which was my favourite, lacks of parametrization.
(And with it, the watchers functionality... but it was the main reference I took, it was the easiest to understand, and the one with more flexibility.)
- Gulp, which was very promising, has a strange API.
(I need flexibility, I can sacrifice a bit of beauty in coding, but I need absolute transparence and flexibility, and also parametrization was not contemplated, and so, the watchers functionality...)
6. Problems
I am not an engineer. I just make tools that fit my needs. But I do not have a deep understanding, or know the best algorythms for doing what I want to do. I can imagine better ways to do them. But I still do not care too much about this point. It may result dangerous, when I do not have the deep knowledge I should have.
In other words: this tool seems to work great for some tasks. But I do not know what can happen if I put a hundred tasks to run, a thousand files to watch, etc.
But... I supose I can split my tasks into different files, and run them selectively, depending on which part of the project I am working on. I do not know. I want to think that I am not losing my time working on tools like this one. In the end, I am already using my own tools for my developments.
7. Conclusions
In conclusion, Taskero
is a project that aims to ease the tasks
automation, which is a very fundamental part of any software
development project, and which takes a lot of time in development.
Also, I wanted to give more open source projects, I can not compite against companies, or engineers, but... maybe I can provide something interesting to them, despite not having a job yet. I do not know.
In fact, I do not want to compite. But it is your language.
This is how you have been programmed. Deeply sad, tbh.