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

smart-pact

v1.0.8

Published

Zero-maintenance contract testing: auto-generates Pact contracts from real traffic, catches data-level regressions, manages service dependencies, and integrates into any CI/CD pipeline.

Readme

SmartPact

A zero-maintenance wrapper around @pact-foundation/pact that solves every major pain point of consumer-driven contract testing at scale.

SmartPact adds an intelligent layer on top of standard Pact by:

  • Auto-generating contracts from real HTTP traffic — no manual interaction writing
  • Detecting data regressions beyond structural checks (the #1 gap in plain Pact)
  • Auto-discovering all consumer-provider relationships from contract files
  • Notifying teams on Slack/webhook when contracts change or break
  • Managing test data using real captured payloads, not synthetic mocks
  • Supporting async/message contracts (Kafka, RabbitMQ, etc.)
  • Integrating into CI/CD with a single command and proper exit codes
  • Providing a click-to-approve workflow for provider API changes

The 8 Problems SmartPact Solves

| # | Pact Limitation | SmartPact Solution | |---|---|---| | 1 | Manual contract creation & maintenance | TrafficRecorder auto-captures real traffic | | 2 | Only tests scenarios you manually defined | Records ALL interactions, 24/7 | | 3 | Catches structure failures, misses data errors | RegressionDetector does deep field/type/value diff | | 4 | Manual cross-team communication on changes | Notifier sends Slack alerts automatically | | 5 | No auto-discovery of service dependencies | DependencyGraphManager builds live graph from contracts | | 6 | Synthetic test data diverges from production | TestDataManager uses real captured payloads | | 7 | Immature async/message support | AsyncMessageRecorder + AsyncContractVerifier | | 8 | Hard to integrate into CI/CD pipelines | CiRunner with GitHub Actions, GitLab, Bitbucket support |


Installation

npm install smart-pact @pact-foundation/pact

Quick Start

1. Create a SmartPact instance

import { SmartPact } from 'smart-pact';

const smartPact = new SmartPact({
  pactDir:      './pacts',
  recordingsDir: './recordings',
  notifications: {
    slack: {
      webhookUrl: process.env.SLACK_WEBHOOK_URL!,
      channel: '#contract-alerts',
      mentionOnBreaking: '@channel',
    },
  },
});

await smartPact.start();
``

### 2. Record real traffic (Express middleware)

```typescript
// Attach to your Express app — captures every request/response automatically
app.use(smartPact.middleware('frontend', 'user-api'));

3. Or record outgoing Axios calls

import axios from 'axios';
smartPact.recordAxios(axios, 'frontend', 'user-api');

4. Generate contracts from recordings

// Run once after traffic is captured (or in CI)
const contractPath = await smartPact.generateContract('frontend', 'user-api');
// → ./pacts/frontend-user-api.json  (fully auto-generated)

5. Verify with deep regression detection

const report = await smartPact.verify('frontend', 'user-api', 'http://user-api:3000');

console.log(report.passed);    // interactions that passed all checks
console.log(report.failed);    // interactions with breaking regressions
console.log(report.findings);  // detailed field-level diffs

6. See your dependency map

smartPact.printDependencyMap();
// ┌────────────────────────────────────┐
//   Service Dependency Map
//   ─────────────────────
//   ✅  user-api
//      └─ consumed by: frontend  (v1.2.0, 8 interactions)
//      └─ consumed by: mobile    (v1.1.0, 5 interactions)
//   ✅  payment-api
//      └─ consumed by: frontend  (v2.0.0, 3 interactions)

7. Run CI/CD verification

// In your CI script
const suite = await smartPact.runCi({
  providerUrls: {
    'user-api':    'http://user-api:3000',
    'payment-api': 'http://payment-api:3001',
  },
  failOnBreaking: true,  // exit code 1 on breaking regressions
});

Regression Detection

SmartPact goes far beyond what standard Pact checks. It detects:

const report = await smartPact.verify('frontend', 'user-api', 'http://user-api:3000');

for (const finding of report.findings) {
  console.log(finding.kind);      // 'field_removed' | 'type_changed' | 'value_changed' | 'field_added' | 'status_changed'
  console.log(finding.severity);  // 'breaking' | 'warning' | 'info'
  console.log(finding.path);      // e.g. 'data.user.phone'
  console.log(finding.expected);  // what the contract said
  console.log(finding.actual);    // what the provider actually returned
}

Example findings:

breaking  field_removed   data.user.phone        (was "+234...", now missing)
breaking  type_changed    data.price             (was number, now string)
breaking  status_changed  status                 (expected 200, got 404)
warning   value_changed   data.user.name         (was "Alice", now "Alice Smith")
info      field_added     data.user.avatarUrl    (new field, non-breaking)

Standard Pact would pass all of the above as long as the top-level structure matches. SmartPact catches them all.


Async / Message Queue Contracts

// Producer side — record messages as they're published
const recorder = smartPact.asyncRecorder('order-service', 'notification-service');

// In your order creation code:
await orderService.createOrder(payload);
await recorder.record('order.created', { orderId: 123, userId: 456, status: 'pending' });

// Auto-generate contract from recorded messages
await recorder.generateContract('./pacts');
// Consumer side — verify your handler processes the contract's messages
const verifier = smartPact.asyncVerifier();
const results = await verifier.verify(contract, async (topic, payload) => {
  await notificationService.handle(topic, payload);
});

Provider Approval Workflow

When a provider changes its API, no more "update the Pact file and tell everyone":

// Provider team: "We're changing the /users endpoint"
const approvals = await smartPact.requestApproval(
  'user-api',
  ['data.user.phone', 'data.user.address'],  // changed fields
  '1.0.0', '2.0.0'
);
// → Slack messages sent to all consumer teams automatically

// Consumer team: approve with one call
await smartPact.approveChange(approvals[0].id, 'team-mobile');

// Or reject it to block the provider deploy
await smartPact.rejectChange(approvals[0].id, 'team-frontend', 'We rely on the phone field');

// See what needs your attention
const pending = await smartPact.getPendingApprovals('frontend');

Test Data with Real Payloads

const data = smartPact.testData();

// Derive provider state fixtures from real traffic
const fixtures = data.deriveFixtures(recorder.getInteractions());
await data.saveFixtures(fixtures);
// → fixtures.json contains actual responses captured from production/staging

// Build real-data mocks to stub downstream dependencies
const mocks = data.buildMocks(recorder.getInteractions());
const mockServer = await smartPact.startMockServer('frontend', 'user-api', 4010);
// → Mock server serves real payloads on http://localhost:4010

CI/CD Integration

GitHub Actions

- name: Run SmartPact contract verification
  run: node scripts/smart-pact-ci.js
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
// scripts/smart-pact-ci.ts
import { CiRunner, writeGitHubActionsOutput } from 'smart-pact';

const runner = new CiRunner();
const suite = await runner.runAndExit({
  pactDir: './pacts',
  providerUrls: {
    'user-api':    process.env.USER_API_URL!,
    'payment-api': process.env.PAYMENT_API_URL!,
  },
  failOnBreaking: true,
});
writeGitHubActionsOutput(suite);

Output in GitHub Actions:

╔═══════════════════════════════════════╗
║         SmartPact CI Runner           ║
║   Zero-maintenance contract testing   ║
╚═══════════════════════════════════════╝

─────────────────────────────────────────
  SmartPact Results  (1243ms)
─────────────────────────────────────────
  ✅  frontend → user-api       (8 interactions, 0 breaking)
  ❌  mobile → payment-api      (3 interactions, 1 breaking)
       ⚠️  [data.price] Type changed: number → string
─────────────────────────────────────────
  Total: 2  ✅ 1  ❌ 1
  Exit code: 1
─────────────────────────────────────────

API Reference

SmartPact

| Method | Description | |---|---| | start() | Start dependency graph watcher | | middleware(consumer, provider) | Express middleware for recording | | recordAxios(axios, consumer, provider) | Axios interceptor for outgoing requests | | generateContract(consumer, provider) | Generate Pact file from recordings | | verify(consumer, provider, url) | Verify + deep regression check | | printDependencyMap() | ASCII graph of all service relationships | | getImpactedServices(provider) | Transitive consumers of a provider | | requestApproval(provider, fields, from, to) | Notify consumers of API change | | approveChange(id, approvedBy) | Consumer approves a change | | rejectChange(id, rejectedBy, reason) | Consumer rejects a change | | getPendingApprovals(consumer?) | Get pending approvals for a consumer | | asyncRecorder(producer, consumer) | Create async message recorder | | asyncVerifier() | Create async contract verifier | | testData() | Access TestDataManager | | startMockServer(consumer, provider, port) | Start real-data mock server | | runCi(opts) | Run full CI verification pipeline |


Configuration

interface SmartPactConfig {
  pactDir:                 string;   // Where to store pact JSON files
  recordingsDir:           string;   // Where to store traffic recordings
  logLevel?:               'debug' | 'info' | 'warn' | 'error';
  deduplicateInteractions?: boolean; // Merge duplicate interactions (default: true)
  versionBump?:            'patch' | 'minor' | 'major'; // Contract version strategy
  notifications?: {
    slack?: {
      webhookUrl:        string;
      channel?:          string;
      mentionOnBreaking?: string;   // e.g. '@channel'
    };
    webhook?: {
      url:      string;
      headers?: Record<string, string>;
    };
    console?: boolean;              // Log to stdout (default: true)
  };
}

Architecture

SmartPact (facade)
│
├── TrafficRecorder          ← Captures real HTTP traffic (Express / Axios)
├── ContractGenerator        ← Builds Pact JSON from recordings + matchers
├── DependencyGraphManager   ← Auto-discovers service relationships
├── RegressionDetector       ← Deep field/type/value diff against live provider
├── Notifier                 ← Slack + webhook alerts
├── TestDataManager          ← Real-data fixtures + mock server
├── AsyncMessageRecorder     ← Records pub/sub messages
├── AsyncContractVerifier    ← Verifies consumer handlers against async contracts
├── ContractManager          ← Orchestrates lifecycle + approval workflow
└── CiRunner                 ← Full CI pipeline runner

License

MIT