Skip to content

Latest commit

History

58 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation



@xlsft/worker

@xlsft/worker – Lightweight, cron, date and event-based task framework with zero-boilerplate setup


Made with <3 and TS

🔗 Table of Contents


⭐ Quick Start

@xlsft/worker is a simple but powerful worker framework. Supported on node, deno and bun. It automatically loads and schedules all *.task.[ts,js,mts,mjs] files from the tasks directory.
Tasks can run on a cron schedule or be triggered by events.

Install @xlsft/worker package

pnpm add jsr:@xlsft/worker # or...
yarn add jsr:@xlsft/worker # or...
npx jsr add @xlsft/worker # or...
bunx jsr add @xlsft/worker

Warning

Do not use deno add jsr:@xlsft/worker! Due to JSR limitations with dynamic imports, it fails when registering tasks!

Create tasks folder and entry file

import{defineWorker}from"@xlsft/worker";defineWorker()

You can pass custom logger or disable logging whatsoever

import{defineWorker}from"@xlsft/worker";constlog=useLogger()// Some loggerdefineWorker({ log })
import{defineWorker}from"@xlsft/worker";defineWorker({log: false})// Disables logging

Also you can change default tasks folder, be aware that it needs to be path from process.cwd()

import{defineWorker}from"@xlsft/worker";defineWorker({dir: 'src/tasks'})

Then run your script with following commands

deno run -A main.ts # or...
bun run main.ts # or...
node main.js

📂 Project Structure & Naming

All tasks must be placed in the tasks directory (or directory of your choice). File names follow the pattern:

<nn(optional)>.<name>.task.[ts,js,mts,mjs]// 01.some_job.task.ts || some_job.task.js || 03.job.task.mjs

Where:

  • nn(optional) — numeric prefix for ordering in directory
  • name — task name
  • .task.[ts,js,mts,mjs] — required suffix

Example:

tasks/
│── 01.cron.task.ts │── 02.event.task.ts
│── other.task.ts

🕒 Task Triggers

A task trigger can be:

  1. Cron based — using TaskCronScheduleSchema-like type or cron syntax
  2. Event based — for manual or cross-task triggering with EventEmitter
  3. Date based - for triggering task only once at some date

Examples:

  1. Cron based cron syntax:
import{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Running every minute');},'* * * * *');
  1. Cron based TaskCronScheduleSchema:
import{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Running every 30 minutes');},{minute: {every: 30}});
  1. Event based:
import{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Triggered by event.emit("event")');},'event');
  1. Event based from generated trigger (from task name):
// name.task.tsimport{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Triggered by event.emit("name")');});// Works with cron tooimport{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Triggered by event.emit("name") and every 30 minutes');},{minute: {every: 30}});
  1. Date based:
// name.task.tsimport{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Triggered at Tue Jan 01 2030 00:00:00');},newDate(2030,0,1));
%%{init: {'flowchart': {'nodeSpacing': 12,'rankSpacing':24}}}%%
flowchart TD
Event[Event Emitter] --> TW
Cron[Cron-like Scheduler] --> TW[Task Workers]
Date[Date Scheduler] --> TW
subgraph TW[ ]
direction BT
TW1[Task Worker 1]
TW2[Task Worker 2]
TW3[Task Worker 3]
TW4[Task Worker ...n]
end
Loading

📣 Task Event

For every task event: TaskEvent class is passed for logging or some other purposes

// event.task.tsimport{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log(event);// TaskEvent {// worker: [Function: worker],// created: 2025-08-14T16:34:31.990Z,// state: { status: "running" },// data: { name: "event", trigger: "event", cron: false },// emit: [Function: emit]// }});

Ensure you doesn`t modify event class, because event is readonly

import{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log(event);event.state.status='canceled';// TS error},{minute: {every: 1}});

📡 Calling a Task from Another Task

You can call (trigger) another task by emitting an event:

// 01.parent.task.tsimport{defineTask}from"@xlsft/worker";exportdefaultdefineTask((event)=>{console.log('Parent job running...');event.emit('children');},{minute: {every: 1}});// 02.children.task.tsimport{defineTask,events}from"tasks";exportdefaultdefineTask((event)=>{console.log('Children job running');},'children');
%%{init: {'flowchart': {'nodeSpacing': 12,'rankSpacing':24}}}%%
flowchart LR
Parent[Parent Task] --> Bus[Event Bus]
Bus --> Child[Child Task]
Loading

🔪 Killing or Canceling Task

You can kill or cancel task using event.kill() or event.cancel()

The difference between canceling and killing a job is that canceling stops only the current run and allows you to start a new one, whereas killing stops the job entirely and it cannot be restarted

// first_job.task.tsimport{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log('Job running');event.cancel();console.log('Unreachable');},'first_job');// second_job.task.tsimport{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log('Start first job');event.emit('first_job');// Works!},{minute: {every: 1}});
// first_job.task.tsimport{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log('Job running');event.kill();console.log('Unreachable');},'first_job');// second_job.task.tsimport{defineTask}from"@xlsft/worker"exportdefaultdefineTask((event)=>{console.log('Start first job');event.emit('first_job');// Doesn`t work :(},{minute: {every: 1}});

⚙️ Task Options

Now you can set 3 different modifications to your worker

  1. retry – number of additional attempts the worker will make if the task fails
  2. times – number of times the task should run in a single execution
  3. delay – time in milliseconds to wait between task executions or retries
exportdefaultdefineTask((event)=>{console.log('Task starts, but fails');thrownewError('Error');},'event',{times: 2,delay: 2000,retry: 5});

In this example:

  • The task will run 2 times (times: 2), but, if it fails, job will retry with 2 times again
  • It will wait 2 seconds between each run or retry (delay: 2000)
  • If it fails, it will retry up to 5 times (retry: 5)

🚧 Project Status

Testing in production — API and internal structure are stable, but needs testing for edge-cases

✅ To do

  • Pass logger into event object with custom prefix
  • Throw an error if try to emit cron string
  • Add an coroutines to tasks (at least try to)
  • Add coroutines docs
  • Add log at start of the task
  • Check for infinity in retry function
  • Retry function in coroutines
  • Emit working on cron triggers by name
  • Depends option in task
  • Add dependencies docs

SmartShell SDK Logo

About

@xlsft/worker – Lightweight, cron, date and event-based task framework with zero-boilerplate setup

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages