incbuild is a utility that relates FS changes to actions that need to be taken. For instance, in a development environment, when changed files needs to be copied around to target folders or when backuping files to another folder or when you need to compile ad-hoc changed/added files.
The tool works by a defined plan required by a configuration file, which allows many features.
- Added CLI
-l
option to list the available watches in a configuration file. See the CLI section. - Added CLI
-s
option to show a configuration of a given watch. See the CLI section. - Watches that are defined with conflicting names are ignored (proper error is given).
Install:
> npm install -g incbuild
Let's start with an example:
watch-config.json
{
"baseRoot": ".",
"watches": [
{
"name": "main",
"watchRoot": ".",
"sources": [ "**/*.json" ],
"ignored": [ "Output" ],
"triggeredCommands": [
{
"triggeringEvents": [ "add", "change" ],
"commands": [ "cp :changedAbsPath: :watchedRoot:/Output/:changedRelFolder:" ]
}
]
}
]
}
Running
> incbuild -f watch-config.json
(See incbuild CLI)
Creates a watch on the current folder (watchRoot
property) that any changed/added .json
file (sources
property) is immediately copied to the relevant path under the Output/
folder.
Note that changes the Output/
folder itself are ignored, per the "ignored"
definition.
If a new folder is created in our watched root, and then we're creating files under that new folder - it does not exist on the relative Output/
path, and so the creation of new files will fail.
In order to handle such FS structure cases, we have the autoCreateDir
configuration property to help. Adding:
"autoCreateDir": ":watchedRoot:/Output/:changedRelPath:"
to the watch, follows up any new folder creation to the target folder where we define (in this example - under the relative path under Output/
folder).
We might want to do some one-time action once the events-watcher is ready. For that, we can use the execAfterReady
property. This executes a command template (see Path templates) once the watcher is ready. For example, run the tsc (TypeScript Compiler) in watch mode for the relevant folder:
"execAfterReady": ":baseRoot:/node_modules/.bin/tsc -w -p :watchedRoot:"
So now, our elaborated example looks like this:
watch-config.json
{
"baseRoot": ".",
"watches": [
{
"watchRoot": ".",
"sources": [ "**/*.json" ],
"ignored": [ "Output" ],
"autoCreateDir": ":watchedRoot:/Output/:changedRelPath:",
"execAfterReady": ":baseRoot:/node_modules/.bin/tsc -w -p :watchedRoot:",
"triggeredCommands": [
{
"triggeringEvents": [ "add", "change" ],
"commands": [ "cp :changedAbsPath: :watchedRoot:/Output/:changedRelFolder:" ]
}
]
}
]
}
Important: It is important to terminate incbuild activity with Ctrl+C, and not rely on parent processes it was started with (like VS Code) doing so, because otherwise incbuild might leave orphan processes (started with the execAfterReady
configuration) running.
The watches
high level property in the JSON definitions file is an array allowing to define many watches. As such, we might want to selectively activate just a few of them. For that there's the watch.name
property which we may reference on the CLI. For example:
watch-config.json
{
"baseRoot": ".",
"watches": [
{
"name": "watch-1",
...
},
{
"name": "watch-2",
...
},
{
"name": "watch-3",
...
},
...
]
}
So we have several watches defined, but we'd like to activate just watch-1 and watch-3:
> incbuild -f watch-config.json watch-1 watch-3
The configuration .json
file carries the following scheme. Note that since this file is require
d, it can also be a Javascript file that exports the relevant configuration object.
{
"baseRoot": string,
"watches": [
{
"name": string,
"executeBeforeReady": boolean,
"watchRoot": string,
"sources": [ string, ... ],
"ignored": [ string, ... ],
"autoCreateDir": CommandTemplate,
"execAfterReady": CommandTemplate,
"triggeredCommands": [
{
"triggeringEvents": [ string, ... ],
"commands": [ CommandTemplate, ... ],
"showStdout": boolean
}
]
}, ...
]
}
A config.schema.json
JSON schema file can be found on the root of the incbuild Javascript installation folder (and also on the root of the Typescript sources in GitHub) for reference and validation of any configuration file given to the incbuild tool.
The configuration object contains the following properties:
Property | Description | Default value |
---|---|---|
baseRoot |
The path to the root folder being watched for changed, relative to the whereabouts of this configuration file. | Mandatory Field |
watches |
Defines a set of watches on the baseRoot folder. A watch is a relation between FS events and what actions to take as consequence. |
Mandatory Field |
watch.name |
The name of the watch. Used to identifiy the watches to activate selectively. When undefined , the watch can't be accessed in such a manner. This is for backward-compatibility. |
undefined |
watch.executeBeforeReady |
Whether to execute actions on relevant FS changes, before the watch is ready. See also FS Events and flows. | false |
watch.watchRoot |
The root folder watched for FS changes, relative to the baseRoot . |
Mandatory Field |
watch.sources |
A list of file paths, relative to the watchRoot folder, for which we are listening for FS events. Accepts Glob definitions. |
Mandatory Field |
watch.ignored |
A list of folders/files, relative to the watchRoot folder, which are to be ignored when watching for FS events. |
[] |
watch.autoCreateDir |
When used, FS folder creation events cause the creation of a matching folders in a path according to the given template. No need to use double-quotes, event for folder names containing spaces. See Path templates. | "" |
watch.execAfterReady |
When used, is a command template to execute after the watch is ready. See FS Events and flows and Path templates. | "" |
watch.triggeredCommands |
A collection of triggering FS events and the actions to take as consequence. | Mandatory Field |
watch.command.triggeringEvents |
A list of FS event names that when triggered causes the given commands to execute. See FS Events and flows. |
Mandatory Field |
watch.command.commands |
A list of command templates to execute when one of the defined triggeringEvents is triggered. Those commands are assumed to be shell commands and are each executed in a separate process. For now, the shell is the same shell as the one used to run incbuild with. |
Mandatory Field |
watch.command.showStdout |
When set, the stdout of the executed command process is written to the console. |
false |
The watching for FS events is done using the chokidar npm ackage.
As such, it defines names for the FS events being watched for. Those names are the names to be used in the watch.command.triggeringEvents
propery list, and currently are:
- add
- addDir
- change
- unlink
- unlinkDir
- ready
- raw
- error
- all
The flow of watch creation is as follows:
- Once such a watch is registered, chokidar scans the folder recursively to find matching files to watch FS events for. Each such file is triggered for with an 'add' event.
- Once the scan is done, the 'ready' event is triggered.
So if the watch.executeBeforeReady
property is set, the 'add' events triggered while scanning will executed the relevant commands. This is good for aligning a target folder with the changes done while the incbuild tool was not running.
The watch.executeBeforeReady
property can define a command to execute once the 'ready' event was triggered, meaning chokidar finished the scan and the watch is ready and running.
All of this activity, and much more, can be seen if running the incbuild tool in debug mode. See Running with debug messages.
Several properties on the configuration JSON schema use the CommandTemplate
type. This is basically a string
, that can accept several wild-cards that are substituted on run time with the relevant required information:
:baseRoot:
is the path relative to the configuration file of the base root for all watches.:watchedRoot:
is the absolute path of the root folder of the watch.:changedAbsPath:
is the absolute path of the changed file/folder.:changedRelPath:
is the path of the changed file/folder, relative to the root of the watch root.:changedFile:
is the name of the changed file (without the prefix-path).:changedRelFolder:
is the path of the folder of the changed file/folder, relative to the watch root.:changedAbsFolder:
is the absolute path of the folder of the changed file/folder.:changeType:
is the name of the triggering event. See FS Events and flows.
The incbuild tool has a simple CLI which syntax can be viewed with the following command:
$ incbuild.js -h
Usage: incbuild [options]
Options:
-V, --version output the version number
-f, --file <path> [[watch] [watch] ...] Specify a watch-definitions file, and optionally select which watches to activate
-l, --list List all available watches (only with -f specified)
-s, --show [watch] Show the configuration of a watch (only with -f specified)
-h, --help output usage information
- Added the ability to selectively activate chosen watches.
- Colored the activated watches in green on the console.
- Minor (required) changes to the CLI.
- Added watch.
name
property to the definition JSON file.
incbuild uses the debug npm package, so in order to see debug message, use the DEBUG
environment variable as described in the debug package documentation.
The incbuild tool is an open-source MIT license project in GitHub.