Skip to main content

Features

Nadle comes packed with powerful features to make your build automation and task management more efficient.

Type Safety​

TypeScript First​

  • Built from the ground up with TypeScript
  • Complete type inference for tasks and configurations
  • Compile-time error detection
  • IDE support with IntelliSense (VS Code, IntelliJ)

Type-Safe Task Options​

import { tasks, defineTask } from "nadle";

interface BuildOptions {
target: "web" | "mobile";
optimize: boolean;
}

const BuildTask = defineTask<BuildOptions>({
run: async ({ options }) => {
const { target, optimize } = options;
// Type-safe access to options
}
});

tasks.register("build", {
run: BuildTask,
options: {
target: "web",
optimize: false
}
});

Parallel Execution​

  • Automatic parallel task execution via worker threads
  • DAG-based dependency resolution
  • Configurable concurrency limits
  • Progress tracking for parallel tasks
tasks.register("build:all", {
run: async () => {
// These tasks will run in parallel if possible
},
dependsOn: ["build:web", "build:mobile", "build:desktop"]
});

Dependency Management​

  • Clear dependency declaration
  • Circular dependency detection
  • Topological sort scheduling
tasks.register("deploy", {
run: async () => {
// Deploy implementation
},
dependsOn: ["build", "test"]
});

Progress Tracking​

Real-Time Progress​

  • Task execution status with interactive footer
  • Scheduled, running, and completed task indicators
  • Time tracking
  • Detailed error reporting

Logging System​

  • Multiple log levels
  • Structured logging
  • Color-coded output
tasks.register("build", async ({ context }) => {
context.logger.info("Starting build...");
context.logger.debug("Debug details...");
// ... build steps
context.logger.warn("Something to watch out for");
});

Available logger methods: log, info, warn, error, debug, throw.

Task Organization​

Grouping and Naming​

  • Logical task groups
  • Consistent naming conventions
  • Task discovery via nadle --list
tasks.register("build:web", {
run: async () => {
// Implementation
},
group: "Build",
description: "Build web application"
});

Error Handling​

Robust Error Management​

  • Detailed error messages
  • Stack trace preservation
tasks.register("deploy", async ({ context }) => {
try {
// Deployment steps
} catch (error) {
context.logger.error("Deployment failed", { error });
// Cleanup or rollback steps
}
});

Caching​

Input Fingerprinting​

Nadle caches task results based on declared inputs and outputs. When inputs haven't changed since the last run, the task is skipped and outputs are restored from cache.

  • Declare file and directory inputs/outputs
  • Cache stored in node_modules/.cache/nadle/ directory
  • Dependency-aware: downstream tasks re-execute when upstream outputs change
  • Task options included in cache key for correct invalidation
  • Automatic eviction of old cache entries (configurable maxCacheEntries)
  • Corruption-resilient: corrupted cache gracefully falls back to re-execution
  • Skip with --no-cache flag
import { tasks, ExecTask, Inputs, Outputs } from "nadle";

tasks.register("compile", {
run: ExecTask,
options: {
command: "tsc",
args: ["--build"]
},
inputs: [Inputs.files("src/**/*.ts", "tsconfig.json")],
outputs: [Outputs.dirs("lib")],
description: "Compile TypeScript sources"
});

Cache Declarations​

  • Inputs.files(...patterns) — declare file input patterns
  • Inputs.dirs(...patterns) — declare directory input patterns
  • Outputs.files(...patterns) — declare file output patterns
  • Outputs.dirs(...patterns) — declare directory output patterns

Environment Variables​

Tasks can set environment variables via the env config field:

tasks.register("build:prod", {
run: async () => {
// Build with production env
},
env: {
NODE_ENV: "production",
MINIFY: true
}
});

Built-in Tasks​

Nadle ships with reusable task types for common operations.

ExecTask​

Run arbitrary shell commands:

import { tasks, ExecTask } from "nadle";

tasks.register("lint", {
run: ExecTask,
options: {
command: "eslint",
args: [".", "--cache"]
}
});

NodeTask​

Run Node.js scripts:

import { tasks, NodeTask } from "nadle";

tasks.register("seed", {
run: NodeTask,
options: {
script: "scripts/seed-db.mjs"
}
});

NpmTask​

Run npm commands:

import { tasks, NpmTask } from "nadle";

tasks.register("install", {
run: NpmTask,
options: {
args: ["install", "--frozen-lockfile"]
}
});

NpxTask​

Run locally-installed binaries via npx:

import { tasks, NpxTask } from "nadle";

tasks.register("lint", {
run: NpxTask,
options: {
command: "eslint",
args: [".", "--cache"]
}
});

PnpmTask​

Run pnpm commands:

import { tasks, PnpmTask } from "nadle";

tasks.register("install", {
run: PnpmTask,
options: {
args: ["install", "--frozen-lockfile"]
}
});

PnpxTask​

Run locally-installed binaries via pnpm exec:

import { tasks, PnpxTask } from "nadle";

tasks.register("build", {
run: PnpxTask,
options: {
command: "tsup",
args: []
}
});

CopyTask​

Copy files with glob patterns:

import { tasks, CopyTask } from "nadle";

tasks.register("copy:assets", {
run: CopyTask,
options: {
from: "src/assets",
to: "dist/assets",
include: ["**/*.png", "**/*.svg"]
}
});

DeleteTask​

Delete files and directories:

import { tasks, DeleteTask } from "nadle";

tasks.register("clean", {
run: DeleteTask,
options: {
paths: ["**/lib/**", "**/build/**"]
}
});

Next Steps​

  1. Dive into Configuration Reference
  2. Explore the API Documentation