c15t
/
Select a framework
Introduction to Runners
Frameworks
Reference
API Reference
CLI Usage
OSS
Contributing
License
C15T Logo
DocsChangelog
xbskydiscordgithub0
c15t
/
Select a framework
Introduction to Runners
Frameworks
Reference
API Reference
CLI Usage
OSS
Contributing
License
home-2Docs
chevron-rightFrameworks
chevron-rightHttp
chevron-rightAdvanced

Advanced Topics

Advanced patterns and best practices for HTTP API

Custom Schema Validators

Runners support Standard Schema-compatible validators, not just Zod:

import { StandardSchemaV1 } from "@standard-schema/spec";
import type { Runner } from "runners";

// Using a custom validator
const CustomInputSchema: StandardSchemaV1<string, string> = {
  "~standard": {
    validate: (value) => {
      if (typeof value !== "string") {
        return { issues: [{ message: "Must be string" }] };
      }
      return { value };
    },
  },
};

export const customRunner: Runner<typeof CustomInputSchema> = async (
  ctx,
  input
) => {
  "use runner";
  // input is typed as string
  return { name: "custom", status: "pass" };
};

Performance Optimization

1. Schema Pre-extraction

Schemas are extracted at build time for performance:

# Build extracts schemas automatically
npm run build

2. Parallel Execution

Use orchestrator for parallel execution:

const runRequest = {
  runners: [/* ... */],
  mode: "remote",
  concurrency: 10, // Run 10 jobs in parallel
};

3. Browser Reuse

Playwright contexts are reused when possible:

// Multiple runners can share browser context
const { page } = await withPlaywright(ctx, url);
// Browser is reused for subsequent runners

4. Lazy Loading

Runners are loaded only when needed:

// Runners loaded on-demand
const runner = await import(`./runners/${runnerName}`);

Error Recovery

Implement retry logic:

async function runWithRetry(
  runner: Runner,
  context: RunnerContext,
  input: unknown,
  maxRetries = 3
) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await runner(context, input);
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      
      // Exponential backoff
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, attempt) * 1000)
      );
    }
  }
}

Testing Runners

Unit Testing

import { describe, it, expect } from "vitest";
import { cookieBannerTest } from "./runners";

describe("cookieBannerTest", () => {
  it("should pass when banner is visible", async () => {
    const context = {
      log: () => {},
      region: "us-east-1",
    };
    
    const result = await cookieBannerTest(context, {
      url: "https://example.com",
    });
    
    expect(result.status).toBe("pass");
  });
});

Integration Testing

import { runRunners } from "runners";
import { cookieBannerTest } from "./runners";

describe("Runner Integration", () => {
  it("should execute runners", async () => {
    const result = await runRunners({
      runners: [cookieBannerTest],
      region: "us-east-1",
    });
    
    expect(result.results).toHaveLength(1);
    expect(result.results[0].status).toBe("pass");
  });
});

Advanced Playwright Usage

Custom Browser Options

import { withPlaywright } from "runners/playwright";

export const customBrowserRunner: Runner = async (ctx, input) => {
  "use runner";
  
  const { browser } = await withPlaywright(ctx, input.url);
  
  // Access browser directly
  const context = await browser.newContext({
    viewport: { width: 1920, height: 1080 },
    userAgent: "Custom User Agent",
  });
  
  const page = await context.newPage();
  // ... use custom page
};

Multiple Pages

export const multiPageRunner: Runner = async (ctx, input) => {
  "use runner";
  
  const { browser } = await withPlaywright(ctx, input.url);
  
  const pages = await Promise.all([
    browser.newPage(),
    browser.newPage(),
    browser.newPage(),
  ]);
  
  // Use multiple pages
  await Promise.all(pages.map(page => page.goto(input.url)));
  
  // ... rest of logic
};

See Also

  • Writing Runners - Runner authoring guide
  • API Reference - Complete API documentation
  • Deployment - Production deployment guide

Available in other SDKs

nitroNitrohonoHono
Runners brings execution, reliability, and distribution to async TypeScript. Build tests and checks that can run locally, in CI, or distributed across regions with ease.
Product
  • Documentation
  • Components
Company
  • GitHub
  • Contact
Legal
  • Privacy Policy
  • Cookie Policy
runners