kubik v0.9.3
Kubik
⚠️ Warning: Kubik is currently in pre-1.0.0 release. Expect potential changes and experimental features that may not be fully stable yet.
Kubik is a simple task runner for node.js with first-class TypeScript support.
Kubik tasks are defined by TypeScript / Node.js scripts, with dependencies to other tasks. Kubik supports running tasks with different parallelization modes and has a built-in watch mode.
- Quick Start
- Getting Started
- Tasks vs Services
- Typescript Support
- Watch Mode
- Parallelization
- Environment Files
- Shebang
- API
- Debugging
Quick Start
Any build.(m)js script can be converted to a task by importing Task and running Task.init in the
very beginning of the script:
import { Task } from 'kubik';
Task.init(import.meta);
/* ... build script ... */The Task.init method accepts configuration (dependencies & watch mode configuration), see
API section.
Use the following commands to run tasks:
- Build:
npx kubik ./build.mjs - Watch mode:
npx kubik -w ./build.mjs - Debug (run without Kubik):
node build.mjsortsx build.mjs - Run sequential build:
npx kubik -j 1 ./build.mjs
A real-life example is available here.
Task dependencies
Kubik allows defining dependencies between tasks using deps option in the Task.init method:
// build-main.mjs
import { Task } from 'kubik';
Task.init(import.meta, {
deps: ['./other-task.mjs'], // these are relative to script folder
});
// ... run some tasksTo run tasks with their dependencies to completion, run:
npx kubik ./build-main.mjsMultiple roots
In a complicated projects, it might be necessary to build a project from multiple entry points. In this case, you can pass multiple entry points to Kubik:
npx kubik ./build-main.mjs ./build-other.mjsIn this case, if both build-main.mjs and build-other.mjs depend on shared.mjs task, then
the task will be executed only once.
Running services
By default, task is considered successful if its process completes with 0 exit code, and unsuccessful if it fails with non-zero code.
However, certain tasks require a running process; for example, launching development server.
In this case, you can use Task.done() to notify Kubik that the task completed and it's dependants
can start executing:
import { Task } from 'kubik';
Task.init(import.meta);
// ...launch HTTP server...
// Report the task as complete.
Task.done();TypeScript support
Kubik supports running tasks defined in a .ts / .mts files using tsx. To use typescript, simply install tsx along side with kubik,
and use .ts/.tsx extension to write your scripts:
Install
tsx:npm i --save-dev tsxWrite your scripts in a
.tsor.mtsfiles:// hello.ts import { Task } from 'kubik'; Task.init(import.meta); const foo: String = 'Hello, typescript!'; console.log(foo);Run your tasks as usual:
npx kubik ./hello.ts
Watch Mode
Kubik supports watch mode where it listens for changes on the file system and reruns tasks and their dependencies.
To run watch mode, use -w or --watch flag:
npx kubik -w ./build.mjsIn watch mode, Kubik launches a terminal app that shows progress, duration and logs from all the tasks:
There are a few shortcuts available to navigate inside the watch mode app:
- To cycle focus through panels, use
TabandShift-Tab - To scroll logs of the focused pane, use arrows,
j,k,Ctrl-U,Ctrl-D,ggandShift-G. - You can also use mouse to scroll logs
By default, Kubik watches for changes in files commonly involved in build tasks, such as:
package.jsonpackage-lock.jsontsconfig.json
However, you can customize files and directories to watch and to ignore during Task initialization:
import { Task } from 'kubik';
Task.init(import.meta, {
deps: ['./build-third-party.mjs'],
watch: ['./src'], // these are relative to script folder
ignore: ['./src/generated'], // these are relative to script folder too
});NOTE: Be careful with watch mode: if the build procedure changes some of the watched files, then Kubik will re-run the build one time, causing "infinite" builds. You'll observe this with tasks never completing. Use
ignoreoption to mitigate this behavior.
Parallelization
Kubik supports -j, --jobs <number> flag to customize number of parallel jobs. By default, Kubik allows an unlimited number of parallel jobs.
Environment Files
Kubik supports -e, --env-file <env file> flag to load environment variables from a file.
npx kubik -e .env ./build.mjsThis will load all the environment variables from .env file, and pass them to all scripts.
Shebang
You can use kubik shebang in scripts, like this:
#!/usr/bin/env npx kubik
import { Task } from 'kubik';
Task.init(import.meta, {
watch: ['./src'],
ignore: ['./src/generated'],
});API
The Task.init function prepares the build environment, offering utilities like $ for shell commands (powered by execa), __dirname, and __filename based on the current script's context.
The whole API boils down to the following:
#!/usr/bin/env npx kubik
import { Task } from 'kubik';
import fs from 'fs';
const {
$, // execa shell runner, that uses __dirname as CWD
__dirname, // **this** script directory absolute path
__filename, // **this** script file absolute path
} = Task.init(import.meta, {
name: 'my library',
watch: ['./src'], // all the paths are resolved relative to this script
ignore: ['./src/generated'], // relative to this script
deps: ['../third-party/build.mjs'], // relative to this script
});
console.log(Task.isWatchMode()); // wether the script is being run under watch mode.
// Use $ to run commands, e.g. typescript.
// Note that $ uses __dirname as CWD.
await $`tsc --pretty -p .`;
// If node.js process does not exit (i.e. it runs a server),
// then we can notify Kubik explicitly that the task is done.
Task.done(); Debugging
You can run build scripts as regular node.js scripts; in this case, these are executed directly by node.js, with no Kubik in the way.
node ./build-main.mjs8 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
8 years ago
9 years ago
9 years ago