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

@soapjs/integr8-express

v1.0.0

Published

Express.js integration for @soapjs/integr8 testing framework

Readme

@soapjs/integr8-express

Express.js integration for @soapjs/integr8 testing framework.

Installation

npm install @soapjs/integr8 @soapjs/integr8-express

Quick Start

// app.ts
import express from 'express';
import { bootstrapExpressIntegr8 } from '@soapjs/integr8-express';

async function start() {
  const app = express();
  
  // Your Express setup
  app.use(express.json());
  app.use('/users', userRoutes);
  
  // Enable Integr8 in test mode
  if (process.env.INTEGR8_MODE === 'true') {
    await bootstrapExpressIntegr8(app, {
      port: 3000,
      enableTestEndpoints: true
    });
  }
  
  app.listen(3000);
}

start();

Usage in Tests

import { setupEnvironment, getEnvironmentContext } from '@soapjs/integr8';

test('should mock service', async () => {
  const ctx = getEnvironmentContext();
  
  await ctx.getCtx().override.service('UserService').withMock({
    findById: async (id) => ({ id, name: 'Mock User' })
  });
  
  const response = await ctx.getHttp().get('/users/123');
  expect(response.data.name).toBe('Mock User');
});

Features

  • Automatic Test Endpoints - /__integr8__/override, /__integr8__/health, /__integr8__/reset
  • Service Mocking - Support for singleton pattern and DI containers
  • Middleware Mocking - Override Express middleware at runtime
  • Built-in DI Container - Optional simple dependency injection container
  • TypeScript Support - Full type definitions included
  • Zero Configuration - Works out of the box for basic use cases

Core Components

bootstrapExpressIntegr8

Bootstrap your Express application with Integr8 testing capabilities:

import { bootstrapExpressIntegr8 } from '@soapjs/integr8-express';

await bootstrapExpressIntegr8(app, {
  port: 3000,
  enableTestEndpoints: true,
  adapterOptions: {
    logger: console  // Optional logger
  }
});

ExpressAdapter

Express adapter implementing Integr8's Adapter interface with enhanced override capabilities:

import { ExpressAdapter } from '@soapjs/integr8-express';

const adapter = new ExpressAdapter();

// Initialize with Express app
await adapter.initialize({
  type: 'express',
  config: {
    app: expressApp,
    logging: 'debug' // optional
  }
});

// Apply overrides
await adapter.applyOverride('service', 'UserService', mockService);
await adapter.applyOverride('middleware', 'authMiddleware', mockMiddleware);
await adapter.applyOverride('provider', 'EmailProvider', mockProvider);

// Check active overrides
const overrides = adapter.getOverrides(); // Returns: ['service:UserService', 'middleware:authMiddleware', ...]

// Clear all overrides (restores original middleware)
await adapter.clearOverrides();

// Teardown
await adapter.teardown();

Override Strategies:

The adapter uses multiple strategies to find and override services:

  1. Service Registry - If app.locals.serviceRegistry exists with an override() method
  2. Setter Pattern - Looks for setXxxService() functions in common service paths
  3. App Locals Storage - Falls back to storing in app.locals.integr8Services

Supported Override Types:

  • service - Business logic services
  • middleware - Express middleware functions
  • provider - Data providers (databases, APIs, etc.)
  • route - Route handlers (experimental)

SimpleContainer

Optional dependency injection container:

import { SimpleContainer } from '@soapjs/integr8-express';

const container = new SimpleContainer();

// Register services
container.register('UserRepository', () => new UserRepository());
container.register('UserService', (c) => {
  return new UserService(c.get('UserRepository'));
});

// Get service instance (singleton by default)
const service = container.get('UserService');

// Override for testing
container.override('UserService', mockService);

// Reset
container.reset(); // Reset all
container.reset('UserService'); // Reset specific service

Test Endpoints

When enableTestEndpoints is true, the following endpoints are available:

GET /integr8/health

Health check with override information:

curl http://localhost:3000/__integr8__/health

Response:

{
  "status": "ok",
  "timestamp": "2025-10-09T12:00:00.000Z",
  "integr8": true,
  "overrides": ["service:UserService", "middleware:auth"]
}

POST /integr8/override

Apply runtime override:

curl -X POST http://localhost:3000/__integr8__/override \
  -H "Content-Type: application/json" \
  -d '{
    "type": "service",
    "name": "UserService",
    "implementation": { "findById": "..." }
  }'

POST /integr8/reset

Clear all overrides:

curl -X POST http://localhost:3000/__integr8__/reset

Service Patterns

Singleton Pattern (without DI)

// services/user.service.ts
let instance: UserService | null = null;

export function getUserService(): UserService {
  if (!instance) instance = new UserService();
  return instance;
}

export function setUserService(service: UserService): void {
  instance = service;
}

// routes/users.ts
import { getUserService } from '../services/user.service';

router.get('/:id', async (req, res) => {
  const service = getUserService();
  const user = await service.findById(req.params.id);
  res.json(user);
});

With DI Container

// container.ts
import { SimpleContainer } from '@soapjs/integr8-express';

const container = new SimpleContainer();
container.register('UserService', (c) => 
  new UserService(c.get('UserRepository'))
);

// app.ts
app.locals.serviceRegistry = container;

// routes/users.ts
router.get('/:id', async (req, res) => {
  const service = req.app.locals.serviceRegistry.get('UserService');
  const user = await service.findById(req.params.id);
  res.json(user);
});

Examples

The package includes three complete examples:

1. Basic Example

Simple Express app with singleton pattern

  • No DI container
  • Setter pattern for testing
  • Basic service mocking

View example

2. With Container Example

Express app with built-in DI container

  • Service-Repository pattern
  • Automatic dependency resolution
  • Easy service mocking

View example

3. Advanced Example

Production-ready Express app

  • Multiple services with dependencies
  • Authentication middleware
  • Caching layer
  • Error handling
  • Request logging

View example

API Reference

Types

interface BootstrapOptions {
  port?: number;
  enableTestEndpoints?: boolean;
  adapterOptions?: AdapterOptions;
}

interface AdapterOptions {
  app?: Application;
  logger?: Logger;
  [key: string]: any;
}

interface Logger {
  debug?(message: string, ...args: any[]): void;
  info?(message: string, ...args: any[]): void;
  warn?(message: string, ...args: any[]): void;
  error?(message: string, ...args: any[]): void;
}

Best Practices

  1. Use DI Container - For better testability and cleaner code
  2. Enable Test Mode Conditionally - Only in test environment
  3. Clear Overrides - Reset state between tests
  4. Type Your Services - Use TypeScript for better IDE support
  5. Organize by Layer - Separate routes, services, and repositories

Testing Examples

Mock Service

test('should mock UserService', async () => {
  const ctx = getEnvironmentContext();
  
  await ctx.getCtx().override.service('UserService').withMock({
    findById: async (id) => ({ id, name: 'Mock' })
  });
  
  const response = await ctx.getHttp().get('/users/123');
  expect(response.data.name).toBe('Mock');
});

Mock Middleware

test('should bypass auth middleware', async () => {
  const ctx = getEnvironmentContext();
  
  await ctx.getCtx().override.middleware('authMiddleware').with(
    (req, res, next) => {
      req.user = { id: 'test', roles: ['admin'] };
      next();
    }
  );
  
  const response = await ctx.getHttp().get('/admin/users');
  expect(response.status).toBe(200);
});

Reset Between Tests

beforeEach(async () => {
  const ctx = getEnvironmentContext();
  await ctx.getAdapter().clearOverrides();
});

Architecture

Adapter Design

The ExpressAdapter follows the same design pattern as the NestJS adapter in @soapjs/integr8:

interface Adapter {
  name: string;
  initialize(config: AdapterConfig): Promise<void>;
  applyOverride(type: string, name: string, implementation: any): Promise<void>;
  teardown(): Promise<void>;
}

Key Features:

  1. Runtime Override System - Modifies services, middleware, and providers at runtime
  2. Multiple DI Strategies - Works with or without dependency injection containers
  3. Middleware Preservation - Saves original middleware for restoration
  4. Comprehensive Logging - Integrates with Integr8's logging system

Comparison with NestJS Adapter:

| Feature | NestJS Adapter | Express Adapter | |---------|----------------|-----------------| | DI System | ModuleRef (built-in) | Optional (SimpleContainer or custom) | | Override Target | Providers, Guards, Interceptors | Services, Middleware, Providers | | Resolution Strategy | Module hierarchy | Registry → Setter → Locals | | State Management | Container-based | Map-based with fallbacks |

How Overrides Work

Service Override Flow:

1. User calls adapter.applyOverride('service', 'UserService', mockImpl)
2. Adapter stores override in Map
3. Adapter tries resolution strategies:
   a. Check app.locals.serviceRegistry.override()
   b. Look for setUserService() function
   c. Store in app.locals.integr8Services
4. Application code retrieves overridden service

Middleware Override Flow:

1. User calls adapter.applyOverride('middleware', 'auth', mockMiddleware)
2. Adapter saves original middleware
3. Adapter finds middleware in Express router stack
4. Replaces layer.handle with new implementation
5. On clearOverrides(), restores original

Compatibility

  • Express: ^4.0.0
  • @soapjs/integr8: ^0.2.1
  • TypeScript: ^5.0.0
  • Node.js: >=16.0.0

License

MIT © SoapJS

Links