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

@xrundev/sdk

v0.0.2

Published

A modern, type-safe task execution framework with built-in middleware support, comprehensive testing capabilities, and production-ready features.

Downloads

6

Readme

XRun SDK

A modern, type-safe task execution framework with built-in middleware support, comprehensive testing capabilities, and production-ready features.

Features

Type-Safe: Full TypeScript support with strict typing
Testable: Comprehensive unit testing support with dependency injection
Middleware System: Plugin-based architecture for cross-cutting concerns
Production Ready: Built-in error handling, timeouts, and retries
Docker Support: Containerized execution with environment-based configuration
Monitoring: Optional metrics collection and structured logging

Quick Start

1. Installation

npm install @xrundev/sdk

2. Define a Task

// tasks/hello-world.ts
import { task } from '@xrundev/sdk';

export const helloWorld = task(
  {
    name: 'hello-world',
    description: 'A simple hello world task',
  },
  async (payload: { name: string }) => {
    return { message: `Hello, ${payload.name}!` };
  }
);

3. Build and Package

# Build the task runner
npx xrun build

# Package as Docker image
npx xrun package

4. Run the Task

docker run --rm \
  -e TASK_ID=hello-world \
  -e TASK_PAYLOAD='{"name": "World"}' \
  -e JOB_ID=job-123 \
  xrun-task-runner:latest

Testing

The SDK includes comprehensive testing support with automatic console mocking to keep test output clean.

Test Setup

All tests automatically include console mocking to prevent log output from cluttering test results. The test setup file (src/test-setup.ts) mocks all console methods globally.

Writing Tests

import { describe, it, expect, vi } from 'vitest';
import { createConsoleSpy } from '../test-setup.js';

describe('My Task', () => {
  it('should execute successfully', async () => {
    // Console output is automatically mocked
    console.log('This will not appear in test output');

    // If you need to verify console calls, use the console spy
    const consoleSpy = createConsoleSpy();

    // Your test logic here
    const result = await myTask({ input: 'test' });

    // Verify console calls if needed
    expect(consoleSpy.log).toHaveBeenCalledWith('Expected message');
  });
});

Console Mocking

The following console methods are automatically mocked in all tests:

  • console.log, console.error, console.warn
  • console.info, console.debug, console.trace
  • console.dir, console.table, console.group
  • console.time, console.count, and more

Architecture

Task Definition

Tasks are defined using the task() function with a configuration and handler:

import { task } from '@xrundev/sdk';

interface MyPayload {
  input: string;
  options?: {
    uppercase?: boolean;
  };
}

interface MyResult {
  output: string;
  metadata: {
    processedAt: string;
  };
}

export const myTask = task<MyPayload, MyResult>(
  {
    name: 'my-task',
    description: 'Processes input with optional transformations',
    runtime: {
      size: 'm', // xs, s, m, l, xl
    },
  },
  async (payload, context) => {
    const { input, options = {} } = payload;
    const { jobId, taskId, taskName } = context;

    let output = input;
    if (options.uppercase) {
      output = input.toUpperCase();
    }

    return {
      output,
      metadata: {
        processedAt: new Date().toISOString(),
      },
    };
  }
);

Middleware System

The SDK includes a powerful middleware system for handling cross-cutting concerns:

Built-in Middleware

import {
  TaskRunner,
  LoggingMiddleware,
  TimeoutMiddleware,
  RetryMiddleware,
  MetricsMiddleware,
} from '@xrundev/sdk';

const runner = new TaskRunner({
  middleware: [
    new LoggingMiddleware(),
    new TimeoutMiddleware(30000), // 30 seconds
    new RetryMiddleware(3, 1000, 2), // 3 retries, 1s delay, 2x backoff
    new MetricsMiddleware((metrics) => console.log(metrics)),
  ],
});

Custom Middleware

import { TaskMiddleware, TaskExecutionContext } from '@xrundev/sdk';

export class AuthMiddleware implements TaskMiddleware {
  name = 'auth';

  async before(context: TaskExecutionContext): Promise<void> {
    // Validate authentication
    const auth = context.metadata?.auth;
    if (!auth) {
      throw new Error('Authentication required');
    }
  }

  async after(context: TaskExecutionContext, result: unknown): Promise<void> {
    // Log successful execution
    console.log(
      `Task ${context.taskId} completed by user ${context.metadata?.userId}`
    );
  }

  async onError(context: TaskExecutionContext, error: Error): Promise<void> {
    // Log authentication failures
    if (error.message.includes('Authentication')) {
      console.error(`Auth failure for task ${context.taskId}`);
    }
  }
}

Configuration

Environment Variables

| Variable | Required | Default | Description | | ---------------- | -------- | ------- | ----------------------------- | | TASK_ID | ✅ | - | The ID of the task to execute | | TASK_PAYLOAD | ✅ | - | JSON payload for the task | | JOB_ID | ✅ | - | Job ID for tracking | | TASK_TIMEOUT | ❌ | 300000 | Timeout in milliseconds | | TASK_RETRIES | ❌ | 0 | Number of retries on failure | | ENABLE_METRICS | ❌ | false | Enable metrics collection |

Runtime Configuration

import { TaskRunner, createDefaultMiddleware } from '@xrundev/sdk';

const runner = new TaskRunner({
  timeout: 60000,
  logger: new CustomLogger(),
  middleware: createDefaultMiddleware({
    timeout: 60000,
    retries: 3,
    enableMetrics: true,
  }),
});

Testing

Unit Testing Tasks

// __tests__/my-task.test.ts
import { describe, it, expect } from 'vitest';
import { myTask } from '../tasks/my-task.js';

describe('myTask', () => {
  it('should process input correctly', async () => {
    const payload = { input: 'hello' };
    const result = await myTask.run(payload);

    expect(result.output).toBe('hello');
    expect(result.metadata.processedAt).toBeDefined();
  });

  it('should handle uppercase option', async () => {
    const payload = { input: 'hello', options: { uppercase: true } };
    const result = await myTask.run(payload);

    expect(result.output).toBe('HELLO');
  });
});

Integration Testing

// __tests__/integration.test.ts
import { describe, it, expect } from 'vitest';
import { TaskRunner, TaskExecutionContext } from '@xrundev/sdk';

describe('Task Integration', () => {
  it('should execute task with full context', async () => {
    const context: TaskExecutionContext = {
      jobId: 'job-123',
      taskId: 'my-task',
      payload: { input: 'test' },
      config: {},
      startTime: Date.now(),
    };

    const runner = new TaskRunner();
    const result = await runner.execute(context);

    expect(result).toBeDefined();
  });
});

Mocking Dependencies

import { vi } from 'vitest';
import { TaskRunner } from '@xrundev/sdk';

const mockMiddleware = {
  name: 'mock',
  before: vi.fn(),
  after: vi.fn(),
  onError: vi.fn(),
};

const runner = new TaskRunner({
  middleware: [mockMiddleware],
});

CLI Commands

Build

npx xrun build [options]

Options:
  -s, --skip-cleanup  Skip cleanup of temporary files

Builds your tasks into a Docker-ready bundle with:

  • Compiled and bundled task definitions
  • Runtime entry point
  • Docker configuration files

Package

npx xrun package

Creates a Docker image with your tasks:

  • Builds a lightweight Alpine-based image
  • Includes all dependencies
  • Configures proper entry point and environment

Advanced Usage

Custom Runtime

For advanced scenarios, you can create a custom runtime:

// custom-runtime.ts
import {
  main,
  TaskRunner,
  createContextFromEnv,
  DefaultLogger,
} from '@xrundev/sdk';
import { CustomMiddleware } from './middleware.js';

// Custom configuration
const customMain = async () => {
  const context = createContextFromEnv();

  const runner = new TaskRunner({
    logger: new DefaultLogger(),
    middleware: [
      new CustomMiddleware(),
      // ... other middleware
    ],
  });

  return runner.execute(context);
};

// Use custom main instead of default
customMain().catch((error) => {
  console.error('Custom runtime error:', error);
  process.exit(1);
});

Error Handling

import { TaskRunnerError } from '@xrundev/sdk';

export const myTask = task(
  { name: 'error-handling-task', description: 'Demonstrates error handling' },
  async (payload: { shouldFail?: boolean }) => {
    if (payload.shouldFail) {
      throw new TaskRunnerError(
        'Task intentionally failed',
        'INTENTIONAL_FAILURE'
      );
    }

    return { success: true };
  }
);

Migration

If you're migrating from the old template-based system, see our Migration Guide for step-by-step instructions.

Examples

Check out the examples directory for more comprehensive examples including:

  • Data processing tasks
  • API integration tasks
  • Batch processing workflows
  • Custom middleware implementations

Contributing

We welcome contributions! Please see our Contributing Guide for details.

License

MIT License - see LICENSE for details.