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

@sahina/cvt-sdk

v0.7.0

Published

Contract Validator Toolkit SDK

Readme

@sahina/cvt-sdk

The Node.js SDK for Contract Validator Toolkit (CVT) — a consumer-driven contract validation platform for OpenAPI v2/v3 specifications.

CVT validates HTTP request/response interactions against registered OpenAPI schemas using a gRPC service. This SDK provides:

  • Schema registration and validation against OpenAPI v2/v3 specs
  • HTTP adapters (Axios, Fetch) for automatic traffic validation
  • Server-side middleware (Express, Fastify) for producer validation
  • Breaking change detection between schema versions
  • Consumer registry and deployment safety checks (can-i-deploy)

For full documentation, visit the CVT Documentation.

Installation

npm install @sahina/cvt-sdk

Usage

1. Initialize and Register Schema

You can register a schema from a local file or a URL.

import { ContractValidator } from "@sahina/cvt-sdk";
import * as path from "path";

const validator = new ContractValidator();

// Register from local file
await validator.registerSchema(
  "my-schema",
  path.resolve(__dirname, "openapi.json"),
);

// OR Register from URL
await validator.registerSchema(
  "petstore",
  "https://petstore.swagger.io/v2/swagger.json",
);

2. Validate Interactions

You can validate requests and responses. The validate method supports generic types for strong typing, or you can use it without types.

Strong Typing (Recommended)

import {
  ContractValidator,
  ValidationRequest,
  ValidationResponse,
} from "@sahina/cvt-sdk";

interface User {
  username: string;
  email: string;
}

const request: ValidationRequest<User> = {
  method: "POST",
  path: "/users",
  headers: { "content-type": "application/json" },
  body: { username: "alice", email: "[email protected]" },
};

const response: ValidationResponse = {
  statusCode: 201,
};

const result = await validator.validate<User>(request, response);

if (result.valid) {
  console.log("✅ Valid interaction");
} else {
  console.error("❌ Validation errors:", result.errors);
}

Untyped Usage

const result = await validator.validate(
  {
    method: "GET",
    path: "/pet/123",
  },
  {
    statusCode: 200,
    body: { id: 123, name: "Fluffy" },
  },
);

HTTP Adapter (Axios)

The SDK includes an Axios adapter for automatic HTTP traffic validation:

import axios from "axios";
import { ContractValidator } from "@sahina/cvt-sdk";
import { createAxiosAdapter } from "@sahina/cvt-sdk/adapters";

const validator = new ContractValidator();
await validator.registerSchema("petstore", "./openapi.json");

const api = axios.create({ baseURL: "https://api.example.com" });

// Auto-validate all requests
const adapter = createAxiosAdapter({
  axios: api,
  validator,
  autoValidate: true,
  excludePaths: ["/health", "/metrics"],
  onValidationFailure: (result, request, response) => {
    console.error("Validation failed:", result.errors);
  },
});

// All requests are now automatically validated
const response = await api.post("/pets", { name: "Fluffy" });

Adapter Options

  • autoValidate: Enable/disable automatic validation (default: true)
  • includePaths: Array of paths/regex to include
  • excludePaths: Array of paths/regex to exclude
  • onValidationFailure: Custom error handler
  • getInteractions(): Retrieve captured interactions
  • clearInteractions(): Reset captured data

Producer Validation (Server-Side Middleware)

Validate incoming requests and outgoing responses against your OpenAPI contract on the server side.

Full documentation: See Validation Modes for detailed behavior, rollout strategy, and metrics information.

Validation Modes

| Mode | Request Violation | Response Violation | Use Case | | ---------- | ----------------- | ------------------ | ---------------------- | | "strict" | Reject with 400 | Log error | Production enforcement | | "warn" | Log, continue | Log, continue | Gradual rollout | | "shadow" | Metrics only | Metrics only | Initial deployment |

Recommended rollout: shadowwarnstrict. See Recommended Rollout Strategy.

Express Middleware

import { ContractValidator } from "@sahina/cvt-sdk";
import { createExpressMiddleware } from "@sahina/cvt-sdk/producer";

const validator = new ContractValidator();
await validator.registerSchema("my-api", "./openapi.json");

app.use(
  createExpressMiddleware({
    schemaId: "my-api",
    validator,
    mode: "strict",
    excludePaths: ["/health", "/metrics"],
  }),
);

Fastify Plugin

import { fastifyProducerPlugin } from "@sahina/cvt-sdk/producer";

fastify.register(fastifyProducerPlugin, {
  schemaId: "my-api",
  validator,
  mode: "strict",
});

Configuration Options

| Option | Type | Description | | ------------------- | ---------------- | ------------------------------------------------ | | schemaId | string | Schema ID to validate against | | validator | Validator | ContractValidator instance | | mode | string | strict, warn, or shadow | | validateRequest | boolean | Enable request validation (default: true) | | validateResponse | boolean | Enable response validation (default: true) | | excludePaths | PathFilter[] | Paths to skip validation (string or RegExp) | | includePaths | PathFilter[] | Only validate matching paths (string or RegExp) | | onRequestFailure | function | Called when request validation fails | | onResponseFailure | function | Called when response validation fails |

Breaking Change Detection

Detect breaking changes between OpenAPI schema versions before deployment:

import { ContractValidator } from "@sahina/cvt-sdk";

const validator = new ContractValidator();

// Register both schema versions
await validator.registerSchemaWithVersion(
  "my-api",
  "./openapi-v1.json",
  "1.0.0",
);
await validator.registerSchemaWithVersion(
  "my-api",
  "./openapi-v2.json",
  "2.0.0",
);

// Compare versions
const result = await validator.compareSchemas("my-api", "1.0.0", "2.0.0");

if (!result.compatible) {
  console.log("Breaking changes detected:");
  result.breakingChanges.forEach((change) => {
    console.log(`- [${change.type}] ${change.description}`);
    if (change.path) {
      console.log(`  Path: ${change.method} ${change.path}`);
    }
  });
  process.exit(1); // Fail CI build
}

Breaking Change Types

| Type | Description | | --------------------------- | ---------------------------------------------- | | ENDPOINT_REMOVED | An endpoint was removed | | REQUIRED_FIELD_ADDED | A required field was added to request | | TYPE_CHANGED | A field's type was changed incompatibly | | REQUIRED_PARAMETER_ADDED | A required query/path/header param was added | | RESPONSE_SCHEMA_CHANGED | Response schema was changed incompatibly | | ENUM_VALUE_REMOVED | An allowed enum value was removed |

See examples/breaking-changes.ts for a complete example.

Producer Testing

Test that your API handlers return responses matching your OpenAPI specification.

ProducerTestKit

import { ProducerTestKit } from "@sahina/cvt-sdk/producer";

const testKit = new ProducerTestKit({
  schemaId: "user-api",
  serverAddress: "localhost:9550",
});

// Validate handler response
const result = await testKit.validateResponse({
  method: "GET",
  path: "/users/123",
  response: {
    statusCode: 200,
    body: { id: "123", name: "Alice", email: "[email protected]" },
  },
});

expect(result.valid).toBe(true);

// Don't forget to close
testKit.close();

Consumer Registry

Track which services depend on your API:

// Register a consumer after successful contract tests
await validator.registerConsumer({
  consumerId: "order-service",
  consumerVersion: "2.1.0",
  schemaId: "user-api",
  schemaVersion: "1.0.0",
  environment: "prod",
  usedEndpoints: [
    { method: "GET", path: "/users/{id}", usedFields: ["id", "email"] },
  ],
});

// List all consumers of a schema
const consumers = await validator.listConsumers("user-api", "prod");

// Deregister a consumer
await validator.deregisterConsumer("order-service", "user-api", "prod");

Deployment Safety (can-i-deploy)

Check if a new schema version can be safely deployed:

const result = await validator.canIDeploy("user-api", "2.0.0", "prod");

if (!result.safeToDeploy) {
  console.error("Cannot deploy:", result.summary);
  for (const consumer of result.affectedConsumers) {
    if (consumer.willBreak) {
      console.error(`- ${consumer.consumerId} will break`);
    }
  }
  process.exit(1);
}

See Producer Testing Guide for complete documentation.

Security Configuration

TLS

const validator = new ContractValidator({
  address: "localhost:9550",
  tls: {
    enabled: true,
    rootCertPath: "./certs/ca.crt", // CA certificate
    certPath: "./certs/client.crt", // For mTLS
    keyPath: "./certs/client.key", // For mTLS
  },
});

API Key Authentication

const validator = new ContractValidator({
  address: "localhost:9550",
  apiKey: "your-api-key-here",
});

Prerequisites

Ensure the CVT gRPC server is running (default: localhost:9550).

Testing

The Node.js SDK includes comprehensive tests covering:

  • Client initialization and configuration
  • Schema registration (local files and URLs)
  • Validation requests and responses
  • Error handling
  • gRPC communication

Running Tests

# Install dependencies
npm install

# Run all tests
npm test

# Run tests with coverage
npm test -- --coverage

# Run specific test file
npm test -- ContractValidator.test.ts

# Run tests in watch mode
npm test -- --watch

Test Structure

tests/
└── ContractValidator.test.ts  # Main SDK test suite

Writing Tests

Example test using Jest:

import { ContractValidator } from "../src";

describe("ContractValidator", () => {
  let validator: ContractValidator;

  beforeEach(() => {
    validator = new ContractValidator("localhost:9550");
  });

  afterEach(async () => {
    await validator.close();
  });

  it("should validate a correct interaction", async () => {
    await validator.registerSchema("test", "./openapi.json");

    const result = await validator.validate(
      { method: "GET", path: "/users" },
      { statusCode: 200, body: [] },
    );

    expect(result.valid).toBe(true);
  });
});

Coverage

The SDK maintains 60%+ test coverage. Generate coverage reports with:

npm test -- --coverage
open coverage/lcov-report/index.html

Development

# Install dependencies
npm install

# Build the SDK
npm run build

# Run linter
npm run lint

# Format code
npm run format:check

# Run example
npm run example