Primitives and helpers for running tasks in TypeScript with support for logging, retries, timeouts, CLI integration, and scheduling.
Replace
npm install
withpnpm add
if you're using pnpm.
npm install uptask
# OR npm install @uptask/core @uptask/cli @uptask/cron
Package | Description | Changelog |
---|---|---|
uptask | Meta-package that re-exports all functionality | |
@uptask/core | Core task management functionality | |
@uptask/cli | Command line interface integration | |
@uptask/cron | Task scheduling with cron expressions |
A meta package uptask
re-exports all functionality from the implementation packages:
import { Task, runTasksCli, scheduleTasks } from 'uptask' // and others functions
The core package provides the main Task
abstract class and utilities for task management.
Note: It is vital to use
as const
when defining task names to ensure type safety.
import { Task, createTasks, findTask } from '@uptask/core'
// Create a custom task
class MyTask extends Task<{ input: string }> {
name = "myTask" as const
async makeComplete() {
const { input } = this.config
this.logger.info(`Processing: ${input}`)
// Task implementation...
return Promise.resolve()
}
}
// Create a fully-typed task registry
const tasks = createTasks([MyTask])
// Configure and run a task (config is fully typed)
tasks.myTask.updateConfig({ input: "test-value" })
await tasks.myTask.run()
// Find a task by criteria
const specificTask = findTask(tasks, task => task.name.includes("my"))
if (specificTask) await specificTask.run({ retries: 3, timeout: 5000 })
// Type-safety
tasks.badTask
// TypeScript error: Property 'badTask' does not exist
The CLI package provides command-line interface support for your tasks.
import { createTasks, Task } from '@uptask/core'
import { runTasksCli } from '@uptask/cli'
import { MyTask, OtherTask } from './tasks.ts'
// Create the task registry
const tasks = createTasks([MyTask, OtherTask])
// Run the CLI
runTasksCli(tasks)
Then run your tasks from the command line:
node script.js --help
node script.js myTask --config '{"input":"value"}'
The cron package provides scheduling capabilities for your tasks.
import { createTasks } from 'uptask/core'
import { scheduleTasks } from 'uptask/cron'
import { DailyTask, HourlyTask } from './tasks.ts'
// Create the task registry
const tasks = createTasks([DailyTask, HourlyTask])
// Schedule tasks with cron expressions
scheduleTasks({
"0 0 * * *": tasks.dailyTask, // Run daily at midnight
"0 * * * *": tasks.hourlyTask, // Run every hour
}, {
timeZone: "America/New_York", // Optional configuration
runOnInit: true, // Run immediately on startup
})
import { Task } from '@uptask/core'
class ApiTask extends Task {
name = "apiRequest" as const
async makeComplete() {
// Implementation...
return Promise.resolve()
}
}
// Run with 3 retries and 10 second timeout
const task = new ApiTask()
await task.run({ retries: 3, timeout: 10000 })
import { batchFunctions } from '@uptask/core'
import { createTasks, batchFunctions, Task } from '@uptask/core'
import { MyTask, OtherTask } from './tasks.ts'
class MyFlow extends Task {
name = "myFlow" as const
type = "flow"
async makeComplete() {
await batchFunctions([
() => tasks.myTask.run({retries: 3, timeout: 10000}),
tasks.otherTask.run,
], { concurrency: 5 })
}
}
It is a common approach to group tasks into flows for better organization and management.
import { createTasks, batchFunctions, Task } from '@uptask/core'
import { scheduleTasks } from '@uptask/cron'
import { MyTask, OtherTask } from './tasks.ts'
class MyFlow extends Task {
name = "myFlow" as const
type = "flow"
async makeComplete() {
await tasks.myTask.run()
await tasks.otherTask.run()
}
}
const flows = createTasks([MyFlow])
scheduleTasks({
"0 0 * * *": flows.myFlow, // Run daily at midnight
})
import { Task } from '@uptask/core'
import { pino } from "pino"
class MyTask extends Task {
name = "myTask" as const
createLogger() {
const logger = pino(...)
return logger.child({ task: this.name })
}
}
See CONTRIBUTING.md for development setup and guidelines.