0.9.3 • Published 5 months ago

kubik v0.9.3

Weekly downloads
1
License
ISC
Repository
github
Last release
5 months ago

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

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.mjs or tsx 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 tasks

To run tasks with their dependencies to completion, run:

npx kubik ./build-main.mjs

Multiple 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.mjs

In 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:

  1. Install tsx:

    npm i --save-dev tsx
  2. Write your scripts in a .ts or .mts files:

    // hello.ts
    
    import { Task } from 'kubik';
    
    Task.init(import.meta);
    const foo: String = 'Hello, typescript!';
    console.log(foo);
  3. 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.mjs

In 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 Tab and Shift-Tab
  • To scroll logs of the focused pane, use arrows, j, k, Ctrl-U, Ctrl-D, gg and Shift-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.json
  • package-lock.json
  • tsconfig.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 ignore option 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.mjs

This 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.mjs
0.9.3

5 months ago

0.1.0

8 months ago

0.3.0

8 months ago

0.2.0

8 months ago

0.9.0

8 months ago

0.8.1

8 months ago

0.8.0

8 months ago

0.7.1

8 months ago

0.9.2

8 months ago

0.9.1

8 months ago

0.5.0

8 months ago

0.4.0

8 months ago

0.7.0

8 months ago

0.6.0

8 months ago

0.5.1

8 months ago

0.0.3

8 years ago

0.0.2

8 years ago

0.0.1

8 years ago