Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@alienfishconsulting/core-context

Strongly typed, functional AsyncLocalStorage wrapper with context propagation for Node.js and Express apps

async-local-storage, async-hooks, nodejs, typescript, context, express, request-context, functional

readme

@alienfishconsulting/core-context

npm version License Node Version

CI codecov

Strongly typed, functional AsyncLocalStorage wrapper for managing request-scoped context in Node.js applications.


✨ Features

  • 🔒 Immutable RequestContext model for tracing and auditing
  • 🧠 Type-safe accessors for contextual fields (e.g., requestId, userId)
  • 🔁 Async context propagation across call stacks
  • 📥 Header integration for tracing across services
  • 🧪 CI-enforced test coverage with Vitest & Nx
  • ⚙️ Framework-agnostic (no Express dependency)

📦 Installation

  pnpm add @alienfishconsulting/core-context

Requires Node.js ≥18.

🧱 Context Model

The RequestContext defines a consistent schema across async boundaries:

interface RequestContext {
  requestId: string;
  correlationId: string;
  userId?: string;
  accountId?: string;
  transactionId?: string;
}

All fields are immutable and meant to persist across the request lifecycle.

🚀 Quick Start

import {
  initWithDefaultContext,
  getContext,
  getContextField,
  runWithContext
} from '@alienfishconsulting/core-context';

initWithDefaultContext(() => {
  const ctx = getContext();
  console.log('Request ID:', ctx?.requestId);
});

Or use a custom context:

const context = {
  requestId: 'abc123',
  correlationId: 'xyz456',
};

runWithContext(context, () => {
  // context is now available inside this function
});

📥 Working with HTTP Headers

import { extractContextFromHeaders, updateContextFromHeaders } from '@alienfishconsulting/core-context';

const headers = {
  'x-request-id': 'abc123',
  'x-user-id': 'user789',
};

updateContextFromHeaders(headers);

// Later...
const userId = getContextField('userId');

🔧 API Overview

Function Description
runWithContext(ctx, fn) Runs fn with the given context
initWithDefaultContext(fn) Auto-generates requestId/correlationId
getContext(fallback?: boolean) Retrieves the current context
assertContext() Returns context or throws if missing
bind(fn) Returns a function bound to the current context
extractContextFromHeaders(headers) Builds a context from header values
updateContextFromHeaders(headers) Extracts + applies context to storage
getContextField(key) Retrieves a specific field from the context

✅ Best Practices

  • Always call runWithContext() at the top level of async workflows

  • Use bind() when passing callbacks to preserve context

  • Avoid mutating context values — treat them as read-only

  • Integrate context extraction in your HTTP layer (e.g., middleware or handlers)

🧪 Testing

This package is managed with Nx and uses Vitest for testing.

pnpm nx test core-context
  • ✅ 80% coverage required

  • 🎯 100% coverage target

  • CI will fail if coverage is insufficient

🛠 Project Structure

  core-context/
  ├── src/
  │   ├── accessors.ts      # Context getters and safety checks
  │   ├── headers.ts        # HTTP header integration
  │   ├── lifecycle.ts      # runWithContext(), bind(), initWithDefaultContext()
  │   ├── storage.ts        # Shared AsyncLocalStorage instance
  │   └── types.ts          # RequestContext schema

This package is part of the @alienfishconsulting/core monorepo — a collection of modular, enterprise-grade TypeScript utilities.

📄 License

MIT

© Terry "Lee" Allen, Jr