npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

scheduledtasks

v1.0.15

Published

A TypeScript-based task scheduler with web dashboard and monitoring

Downloads

296

Readme

TaskScheduler

A lightweight TypeScript-based task scheduler with a simple web dashboard and APIs for monitoring and manually triggering scheduled tasks.

This project runs scheduled task groups (cron-based) that execute TypeScript task modules. Each task module is a class that extends MonitoredScheduledTask (see src/MonitoredScheduledTask.ts) and emits progress, status and summary updates that are stored in a local database.

Key features

  • Cron-based task groups
  • Per-task progress/reporting via event-driven MonitoredScheduledTask subclasses
  • Web dashboard with live status and manual triggers
  • REST API endpoints for status, task summary, errors and manual execution
  • Simple configuration via a JSON file (see data/example_task_config.json)

Installation

As a standalone application

  1. Clone this repository
  2. Install dependencies
npm install
  1. Copy the example config to data/task_config.json and adjust it to your needs:
copy data\example_task_config.json data\task_config.json
  1. Start the server (uses ts-node to run TypeScript in-place):
npm start
  • The server will start on http://localhost:3000 by default (or PORT env var).
  • Dashboard: http://localhost:3000/task-scheduler
  • Health: http://localhost:3000/health

Run in development with automatic reload (watch):

npm run dev

There are also existing scheduler scripts in package.json (if present) which run TaskScheduler-start.ts.

As a Node.js module

You can also install this as a dependency in another Node.js project:

npm install scheduledtasks

Then use it in your project:

import { TaskScheduler, MonitoredScheduledTask, TaskStatus } from 'scheduledtasks';
import express from 'express';

// Create a custom task
class MyCustomTask extends MonitoredScheduledTask {
  protected async execute(): Promise<void> {
    this.updateProgress('Starting my task...', 0);
    // Do your work here
    await this.doSomeWork();
    this.updateProgress('Task completed!', 100);
    this.setSummary('Successfully processed data');
  }

  private async doSomeWork(): Promise<void> {
    // Your task logic here
  }
}

// Set up the scheduler
const scheduler = new TaskScheduler('path/to/your/task_config.json');
scheduler.start();

// Optional: Set up web dashboard
const app = express();
const { setupDashboard } = require('scheduledtasks');
const path = require('path');

// The setupDashboard function will automatically find the web directory
// But you can also specify it manually if needed:
// const webDir = path.join(__dirname, 'node_modules', 'scheduledtasks', 'web');
// await setupDashboard(app, scheduler, webDir);

await setupDashboard(app, scheduler);
app.listen(3000);

Configuration file format remains the same, but your filePath should point to your custom task modules.

Configuration: example_task_config.json

The scheduler is configured with a JSON file containing an array of task groups. A minimal example is included at data/example_task_config.json.

Top-level structure:

  • groupName (string): Logical name for the task group
  • cron (string): Cron expression (node-cron format) describing when the group runs
  • tasks (array): List of tasks in this group

Each task object:

  • name (string): Name of the task (used to identify last runs)
  • filePath (string): Path to the TypeScript task module (relative or absolute). Example: src/TestTask.ts
  • params (object): Arbitrary key/value params passed to the task constructor
  • warningHours (number): Hours threshold for "warning" age of a task
  • errorHours (number): Hours threshold for "error" age of a task
  • killOnFail (boolean, optional): If true, stops remaining tasks in group on failure

Example (from data/example_task_config.json):

[
  {
    "groupName": "Test Group",
    "cron": "*/5 * * * *",
    "tasks": [
      {
        "name": "Test Task",
        "filePath": "src/TestTask.ts",
        "params": { "testParam": "hello world" },
        "warningHours": 0.1,
        "errorHours": 0.05,
        "killOnFail": false
      }
    ]
  }
]

How to use your own config:

  1. Create a copy of the example file and name it data/task_config.json.
  2. Update filePath to point to your task module file(s).
  3. Start the server and verify groups load (console logs list scheduled groups).

Notes:

  • filePath values are resolved using path.resolve(), so relative paths are resolved against the process working directory (project root when running via npm start).
  • The scheduler dynamically requires task modules at runtime and expects a default export (see "Extending MonitoredScheduledTask" below).

API Endpoints (prefix: /task-scheduler/api/)

The server exposes the following REST endpoints for the dashboard and automation:

  • GET /task-scheduler/api/status — Returns general scheduler status (isRunning, scheduled groups, running tasks)
  • GET /task-scheduler/api/task-summary — Returns grouped task summaries including last run info and live progress
  • GET /task-scheduler/api/errors?hours=N — Returns error tasks within the last N hours (default 24)
  • POST /task-scheduler/api/run-group/:groupName — Manually trigger a whole task group (async)
  • POST /task-scheduler/api/run-task/:groupName/:taskName — Manually trigger a single task within a group (async)
  • POST /task-scheduler/api/cleanup — Cleanup old DB records; expects body { days: number }

Use these endpoints from the dashboard UI (already wired in the web/ pages) or via scripts/automation.

Extending MonitoredScheduledTask (create your own task)

Task modules are TypeScript files that default-export a class that extends MonitoredScheduledTask from src/MonitoredScheduledTask.ts.

Contract / expectations:

  • Export default a class that extends MonitoredScheduledTask.
  • Constructor signature: constructor(taskName: string, taskId: string, params: Record<string, any> = {}) — call super(taskName, taskId, params) in your constructor.
  • Implement the protected async execute(): Promise<void> method. This is where the task does its work.
  • Use the helper methods inside your task to report state:
    • this.updateProgress(message: string, percentage?: number) — emit progress updates for the dashboard/DB
    • this.setSummary(summary: string) — set a final summary string
    • this.setError(errorMessage: string) — mark the task as errored and emit status change
    • this.skip(reason: string) — mark task as skipped

Events emitted by base class (useful for tests):

  • statusChanged — emitted when status changes (created, in_progress, completed, error, skipped)
  • progressUpdated — emitted when progress updates
  • summaryUpdated — emitted when summary changes

Minimal example (see src/TestTask.ts):

import { MonitoredScheduledTask } from './ScheduledTask';

export default class TestTask extends MonitoredScheduledTask {
  constructor(taskName: string, taskId: string, params: any = {}) {
    super(taskName, taskId, params);
  }

  protected async execute(): Promise<void> {
    this.updateProgress('Starting...', 0);
    // ... do work
    this.updateProgress('Done', 100);
    this.setSummary('Completed successfully');
  }
}

Important: dynamic loading will require() the resolved filePath. The module must be loadable via Node's require (TypeScript + ts-node allows .ts files at runtime when using ts-node).

Example project structure when using as a module

my-project/
├── package.json
├── src/
│   ├── tasks/
│   │   ├── DataSyncTask.ts
│   │   └── ReportTask.ts
│   └── server.ts
├── config/
│   └── task_config.json
└── tsconfig.json

Example package.json:

{
  "name": "my-scheduled-app",
  "dependencies": {
    "scheduledtasks": "^1.0.0",
    "typescript": "^5.0.0",
    "ts-node": "^10.0.0"
  },
  "scripts": {
    "start": "ts-node src/server.ts"
  }
}

Publishing to npm

If you want to publish this as your own npm package:

npm run build
npm publish

The prepublishOnly script will automatically build the project before publishing.

Database

A local SQLite database (TaskScheduler.db) is used via better-sqlite3 and is managed by src/DatabaseManager.ts. The DB stores task groups, task runs, errors and metadata.

Troubleshooting

  • TypeScript .ts import errors: ensure tsconfig.json exists (this project includes one) and ts-node is installed (devDependency). npm start uses npx ts-node.
  • Port conflicts: if EADDRINUSE occurs, ensure nothing else is listening on the configured PORT (default 3000); stop other processes or change PORT env var.
  • Dashboard pages not found (404 errors): The dashboard pages are under web/ directory. When used as a node module, the setupDashboard function automatically detects the correct path. If you get 404 errors, check the console logs for the web directory path being used.
  • Web directory path issues: If the automatic detection fails, you can manually specify the web directory:
    const path = require('path');
    const webDir = path.join(__dirname, 'node_modules', 'scheduledtasks', 'web');
    await setupDashboard(app, scheduler, webDir);
  • Task module loading errors: check the filePath and ensure the file default-exports a class extending MonitoredScheduledTask.

Contributing & Next steps

  • Add unit tests for task modules and DatabaseManager
  • Add authentication for dashboard API if exposing publicly
  • Add better validation for task_config.json (schema & helpful errors)

If you want, I can also add a small example data/task_config.json (copied from the example file) and a short script to validate configs. Would you like that?