@betabong/dotask
v1.0.6
Published
A flexible task runner for executing TypeScript and JavaScript tasks
Maintainers
Readme
dotask
A flexible task runner for executing TypeScript and JavaScript tasks. Supports both CLI and programmatic API usage.
Features
- ✅ Execute TypeScript and JavaScript files without pre-compilation
- ✅ Support
task:functionsyntax to call specific exports - ✅ Series execution (sequential)
- ✅ Parallel execution
- ✅ Configurable task directory
- ✅ Beautiful console output with emojis and timing
- ✅ Error handling with proper exit codes
- ✅ Configuration file support (
dotask.config.ts) - ✅ Full TypeScript type definitions
- ✅ Zero-config default behavior
Installation
npm install -D dotaskQuick Start
1. Create a tasks directory
mkdir tasks2. Create your first task
// tasks/hello.ts
import type { TaskContext } from 'dotask'
export default async function(ctx: TaskContext) {
ctx.log('Hello from dotask!')
}3. Run the task
npx dotask helloCLI Usage
Single Task
dotask taskNameNamed Function Export
dotask taskName:functionNameMultiple Tasks (Series)
dotask task1 task2 task3Tasks run sequentially, one after another.
API Usage
Basic Usage
import { run, series, parallel } from 'dotask'
// Run a single task
await run('taskName')
await run('taskName:functionName')
// Run tasks in series
await series('task1', 'task2', 'task3')()
// Run tasks in parallel
await parallel('task1', 'task2', 'task3')()
// Pass function directly
await run(async (ctx) => {
ctx.log('Running inline task')
})Configuration
import { configure } from 'dotask'
configure({
tasksDir: './custom-tasks',
logger: {
log: (msg) => console.log(`[CUSTOM] ${msg}`),
error: (msg) => console.error(`[ERROR] ${msg}`),
info: (msg) => console.info(`[INFO] ${msg}`),
},
onTaskStart: (taskName) => {
console.log(`Starting: ${taskName}`)
},
onTaskComplete: (taskName, duration) => {
console.log(`Completed: ${taskName} in ${duration}ms`)
},
onTaskError: (taskName, error) => {
console.error(`Failed: ${taskName}`, error)
},
})Configuration File
Create a dotask.config.ts file in your project root:
import { defineConfig } from 'dotask'
export default defineConfig({
// Base directory for tasks (default: './tasks')
tasksDir: './tasks',
// Custom logger
logger: {
log: (msg: string) => console.log(msg),
error: (msg: string) => console.error(msg),
info: (msg: string) => console.info(msg),
},
// Task execution hooks
onTaskStart: (taskName: string) => {
console.log(`🚀 Starting ${taskName}`)
},
onTaskComplete: (taskName: string, duration: number) => {
console.log(`✨ Completed ${taskName} in ${duration}ms`)
},
onTaskError: (taskName: string, error: Error) => {
console.error(`💥 Error in ${taskName}:`, error)
},
})Task File Format
Default Export
// tasks/myTask.ts
import type { TaskContext } from 'dotask'
export default async function(ctx: TaskContext) {
ctx.log('Running my task')
// Task implementation
}Named Exports
// tasks/build.ts
import type { TaskContext } from 'dotask'
export async function dev(ctx: TaskContext) {
ctx.log('Building for development')
// Development build
}
export async function prod(ctx: TaskContext) {
ctx.log('Building for production')
// Production build
}Run with:
dotask build:dev
dotask build:prodTask Context
Tasks receive a TaskContext object with useful utilities:
interface TaskContext {
log: (msg: string) => void // Colored log output
error: (msg: string) => void // Colored error output
info: (msg: string) => void // Colored info output
}Examples
Example: Build Task
// tasks/build.ts
import type { TaskContext } from 'dotask'
import { exec } from 'node:child_process'
import { promisify } from 'node:util'
const execAsync = promisify(exec)
export default async function(ctx: TaskContext) {
ctx.log('Building project...')
await execAsync('npm run build')
ctx.log('Build complete!')
}Example: Series Execution
// tasks/deploy.ts
import { series } from 'dotask'
export default series(
'clean',
'build',
'test',
'deploy'
)Example: Parallel Execution
// tasks/lint.ts
import { parallel } from 'dotask'
export default parallel(
'lint:eslint',
'lint:prettier',
'lint:typescript'
)Example: Complex Task
// tasks/setup.ts
import type { TaskContext } from 'dotask'
import { series, parallel } from 'dotask'
export default async function(ctx: TaskContext) {
ctx.log('Setting up project...')
// Run some tasks in parallel
await parallel('install:deps', 'setup:config')()
// Then run sequential tasks
await series('build', 'test')()
ctx.log('Setup complete!')
}TypeScript Support
dotask uses tsx under the hood to execute TypeScript files directly. No compilation step required!
Your task files can use:
- TypeScript syntax
- ES Modules (
import/export) - Type definitions
- Modern JavaScript features
Error Handling
Tasks that throw errors will:
- Display an error message
- Set
process.exitCode = 1 - Call the
onTaskErrorhook (if configured) - Stop execution (in series mode)
Development
Building
npm install
npm run buildThis compiles TypeScript to JavaScript in the dist/ directory.
Development Mode
For local development, you can use:
npm run dev taskNameThis runs the CLI directly from source using tsx.
Requirements
- Node.js >= 18.0.0
- TypeScript (optional, for TypeScript task files)
License
MIT
