New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

micro-contracts

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

micro-contracts

Contract-first OpenAPI toolchain that keeps TypeScript UI and microservices aligned via code generation

latest
Source
npmnpm
Version
0.13.0
Version published
Maintainers
1
Created
Source

micro-contracts

npm version License: MIT Node.js TypeScript OpenAPI

Contract-first vertical slices for TypeScript Web/API systems.

micro-contracts is a contract-first toolchain for TypeScript Web/API development. It tackles common failure modes—frontend/backend contract drift, duplicated "common" rules, and accidental breaking changes in public APIs—by treating OpenAPI as the Single Source of Truth (SSoT).

Contracts alone aren't enough—they must be enforceable. micro-contracts includes Enforceable Guardrails that prevent both humans and AI from bypassing the contract-first workflow: blocking direct edits to generated files, detecting drift, and verifying security declarations match implementations.

Design Philosophy

Architecture

The core architecture is organized along two axes:

AxisDescriptionExample
Vertical (feature-aligned slices)A module is a feature-aligned contract boundary. The same contract spans UI (frontend) and API (backend).core, billing, users
Horizontal (cross-cutting concerns)Auth, tenancy, rate limiting, and shared error behavior are applied consistently via OpenAPI Overlays.x-middleware: [requireAuth, tenantIsolation]

Key Differentiators

#DifferentiatorWhat it means
1Vertical Modules + Horizontal OverlaysFeature-aligned modules as contract boundaries; cross-cutting concerns (auth, rate-limit) injected via OpenAPI Overlays.
2OpenAPI as SSoT → Multi-artifact generationSingle spec generates contract packages, server routes, and frontend clients. No manual sync required.
3Enforceable GuardrailsBuilt-in checks prevent bypassing contract-first workflow—blocks direct edits to generated files, detects drift, verifies security declarations. See Guardrails.
4Public Surface Governancecontract-published is extracted (not duplicated) from the master contract. x-micro-contracts-non-exportable fails generation if internal data leaks.
5Explicit Module Dependenciesx-micro-contracts-depend-on declares cross-module dependencies. deps/ re-exports only declared types; enables impact analysis.
6Screen SpecDeclare frontend screen contracts (ViewModel, navigation, analytics events) in OpenAPI. One YAML drives typed navigation maps and event hooks. See Screen Spec.

Who is this for?

ScenarioWhy micro-contracts helps
Modular monolith → microservicesSame contracts work in monolith or split services; dependency tracking prevents hidden coupling
Multiple teams sharing OpenAPIExplicit module dependencies make cross-team impact visible
Published API with compatibility SLAcontract-published extraction + x-micro-contracts-non-exportable fail-fast prevents accidental exposure
Cross-cutting concerns at scaleOpenAPI Overlays inject auth/rate-limit/tenancy and extension properties without copy-paste

Not the best fit for: Single-developer projects, auto-generated UI from schema, multi-language SDK generation (use OpenAPI Generator instead).

Quick Start

Prerequisites: Node.js 18+, TypeScript 5.0+, ESM ("type": "module").

# 1. Install
npm install --save-dev micro-contracts

# 2. Initialize module structure
npx micro-contracts init core --openapi path/to/your/spec.yaml

# 3. Generate all code
npx micro-contracts generate
// 4. Use in your server
import { registerRoutes } from './core/routes.generated.js';
await registerRoutes(fastify);

What init creates: The init command creates starter templates for Fastify (server) and fetch API (client). These are scaffolds to get you started — modify them for your framework (Express, Hono, Axios, etc.) or add new output types.

📦 Full working example: See examples/ for a complete project with multiple modules, overlays, and cross-module dependencies.

Core Concepts

OpenAPI as Single Source of Truth (SSoT)

OpenAPI spec (spec/{module}/openapi/*.yaml)
    ↓ micro-contracts generate
Contract packages (packages/contract/{module}/)
    ├── schemas/types.ts       # Request/Response types
    ├── services/              # Service interfaces
    └── overlays/              # Overlay handler interfaces
    ↓
Server routes + Frontend clients (generated via templates)

Modules vs Services

ConceptDefinitionExample
ModuleLogical contract boundary (OpenAPI + Service)core, billing, users
ServiceDeployment unit (can contain 1+ modules)api-server

A monolith may have multiple modules in one service. Start with multiple modules in one service and split later as needed.

Contract Packages

PackageDescriptionCompatibility Policy
contractMaster contract (all APIs)Internal APIs can change freely
contract-publishedPublic APIs only (x-micro-contracts-published: true)Must maintain backward compatibility

Key insight: contract-published is extracted from contract (not generated separately). This ensures a single SSoT.

Cross-cutting Concerns with Overlays

  • Mark operations with x-middleware (or custom extensions) in OpenAPI
  • Define overlay that adds params/responses when extension is present
  • Generator applies overlays and produces openapi.generated.yaml
  • Generate code from the result

📖 Deep Dive: See OpenAPI Overlays (Deep Dive) for complete examples and configuration.

Screen Spec — Frontend Screen Contracts

Standard OpenAPI constructs can also define frontend screen contracts — bridging the API layer and UI components. A single YAML file drives ViewModel types, typed navigation maps, and analytics event hooks.

Screen Spec (OpenAPI YAML)
  ├── ViewModel Types       (from schemas — zero new template work)
  ├── Navigation Map        (from response links → typed routing)
  └── Event Hooks           (from x-events → typed analytics)

Enable with screen: true in module config:

modules:
  myScreens:
    openapi: spec/screens/screens.yaml
    screen: true
    outputs:
      screen-navigation:
        output: frontend/src/screens/navigation.generated.ts
        template: screen-navigation.hbs
      screen-events:
        output: frontend/src/screens/events.generated.ts
        template: screen-events.hbs

Initialize a screen module with starter files:

npx micro-contracts init myScreens --screens

📖 Deep Dive: See Screen Spec for the full guide — YAML structure, x-screen-* extensions, TemplateContext.screens, lint rules, and custom template examples.

Directory Structure

project/
├── spec/                              # ✅ Human-edited (contract source of truth)
│   ├── spectral.yaml                  #    Global lint rules
│   ├── default/templates/             #    Handlebars templates (customizable)
│   ├── _shared/
│   │   ├── openapi/                   #    Shared schemas (ProblemDetails, etc.)
│   │   └── overlays/                  #    Cross-module overlays
│   └── {module}/
│       ├── openapi/{module}.yaml      #    OpenAPI spec
│       └── overlays/                  #    Module-specific overlays
│
├── packages/                          # ❌ Auto-generated (DO NOT EDIT)
│   ├── contract/{module}/
│   │   ├── schemas/                   #    Types, validators
│   │   ├── services/                  #    Service interfaces
│   │   ├── overlays/                  #    Overlay handler interfaces
│   │   └── deps/                      #    Re-exports from dependencies
│   └── contract-published/{module}/   #    Public API subset
│
├── server/src/{module}/
│   ├── routes.generated.ts            # ❌ Auto-generated (template: fastify-routes.hbs)
│   ├── services/                      # ✅ Human-edited (service implementations)
│   └── overlays/                      # ✅ Human-edited (overlay implementations)
│
└── frontend/src/{module}/
    └── api.generated.ts               # ❌ Auto-generated (template: fetch-client.hbs)

Note: *.generated.ts files are generated from Handlebars templates in spec/default/templates/. You can customize or replace templates for different frameworks (Express, Hono, Axios, etc.).

Why commit generated files? Generated artifacts are committed to enable code review of contract changes and CI drift detection. If spec changes but generated code doesn't match, CI fails.

OpenAPI Extensions

Required Extensions

ExtensionTypeDescription
x-micro-contracts-servicestringService class name (e.g., User, Order)
x-micro-contracts-methodstringMethod name to call (should match operationId)

Optional Extensions

ExtensionTypeDescription
x-micro-contracts-publishedbooleanInclude in contract-published (compatibility SLA)
x-micro-contracts-non-exportablebooleanMark as non-exportable (fails if used in published endpoints)
x-micro-contracts-depend-onstring[]Explicit dependencies on other modules' published APIs

Screen Spec Extensions

Used in modules with screen: true. See Screen Spec for details.

ExtensionTypeDescription
x-screen-conststringStable constant name (e.g., HOME)
x-screen-idstringTraceability ID (e.g., SCR-001)
x-screen-namestringGenerated symbol name (e.g., HomePage)
x-back-navigationbooleanSupports history-based back navigation
x-eventsarrayAnalytics event declarations ({name, type, method, params?})

Example

paths:
  /api/users:
    get:
      operationId: getUsers
      x-micro-contracts-service: User
      x-micro-contracts-method: getUsers
      x-micro-contracts-published: true
      x-middleware: [requireAuth]            # Custom extension for overlays
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListResponse'

Module Dependencies

Declare dependencies with x-micro-contracts-depend-on:

# spec/billing/openapi/billing.yaml
info:
  x-micro-contracts-depend-on:
    - core.User.getUsers
    - core.User.getUserById

Import via generated deps/:

// ✅ Recommended: Import from deps/
import type { User } from '@project/contract/billing/deps/core';

// ❌ Avoid: Direct contract-published import
import type { User } from '@project/contract-published/core/schemas';

Configuration

Create micro-contracts.config.yaml. All paths support {module} placeholder.

defaults

KeyTypeRequiredDescription
contract.outputstringyesOutput directory for contract packages
contract.serviceTemplatestringnoCustom Handlebars template for service interface generation
contractPublic.outputstringyesOutput directory for public contract packages
outputs.<id>.outputstringyesOutput file path
outputs.<id>.templatestringyesHandlebars template file path
outputs.<id>.overwritebooleannoOverwrite existing files (default: true)
outputs.<id>.conditionstringnohasPublicEndpoints | hasOverlays | always (default: always)
outputs.<id>.enabledbooleannoEnable/disable this output (default: true)
outputs.<id>.configobjectnoTemplate-specific configuration passed to context
overlays.sharedstring[]noOverlay files applied to all modules
overlays.collisionstringnoerror | warn | last-wins (default: error)
docs.enabledbooleannoEnable documentation generation (default: true)
docs.templatestringnoDocumentation template
sharedModuleNamestringnoShared module name for overlays

modules.<name>

KeyTypeRequiredDescription
openapistringyesPath to OpenAPI spec file
screenbooleannoEnable screen spec mode (x-screen-* extensions, TemplateContext.screens)
contract.outputstringnoOverride contract output directory
contract.serviceTemplatestringnoOverride custom service interface template
contractPublic.outputstringnoOverride public contract output directory
outputs.<id>.enabledbooleannoEnable/disable specific output for this module
outputs.<id>.*noOverride any output config field
overlaysstring[]noModule-specific overlay files
dependsOnstring[]noDependencies ({module}.{service}.{method})
spectralstringnoModule-specific Spectral config path
docs.enabledbooleannoOverride documentation generation

Example

defaults:
  contract:
    output: packages/contract/{module}
  contractPublic:
    output: packages/contract-published/{module}
  outputs:
    server-routes:
      output: server/src/{module}/routes.generated.ts
      template: spec/default/templates/fastify-routes.hbs
    frontend-api:
      output: frontend/src/{module}/api.generated.ts
      template: spec/default/templates/fetch-client.hbs
  overlays:
    shared:
      - spec/_shared/overlays/middleware.overlay.yaml

modules:
  core:
    openapi: openapi/core.yaml
  billing:
    openapi: openapi/billing.yaml
    dependsOn:
      - core.User.getUsers
    outputs:
      frontend-api:
        enabled: false

CLI Reference

generate

Generate code from OpenAPI specifications.

OptionDescription
-c, --config <path>Path to config file
-m, --module <names>Module names, comma-separated (default: all)
--contracts-onlyGenerate contract packages only
--server-onlyGenerate server routes only
--frontend-onlyGenerate frontend clients only
--docs-onlyGenerate documentation only
--skip-lintSkip linting before generation
--no-manifestSkip manifest generation
--manifest-dir <path>Directory for manifest (default: packages/)
--forceBypass input hash cache and always regenerate
--no-cacheRun without reading or writing input hash cache

init <module>

Initialize a new module structure with starter templates.

OptionDescription
-d, --dir <path>Base directory (default: src)
-i, --openapi <path>OpenAPI spec to process (auto-adds extensions)
-o, --output <path>Output path for processed OpenAPI
--skip-templatesSkip creating starter templates
--screensInitialize as screen spec module (generates screen templates and starter spec)

lint <input>

Lint OpenAPI specification.

OptionDescription
--strictTreat warnings as errors

check

Run guardrail checks.

OptionDescription
--only <checks>Run only specific checks (comma-separated)
--skip <checks>Skip specific checks (comma-separated)
--gate <gates>Run checks for specific gates only (1-5)
-v, --verboseEnable verbose output
--fixAuto-fix issues where possible
-g, --guardrails <path>Path to guardrails.yaml
-d, --generated-dir <path>Path to generated files directory (default: packages/)
--changed-files <path>Path to file containing changed files (for CI)
--listList available checks
--list-gatesList available gates

pipeline

Run full guardrails pipeline: Gate 1,2 → Generate → Gate 3,4,5.

OptionDescription
-c, --config <path>Path to config file
-v, --verboseEnable verbose output
--skip <checks>Skip specific checks (comma-separated)
--continue-on-errorContinue running even if a step fails
-g, --guardrails <path>Path to guardrails.yaml
-d, --generated-dir <path>Path to generated files directory (default: packages/)
--no-manifestSkip manifest generation
--skip-lintSkip linting before generation
--contracts-onlyGenerate contract packages only
--server-onlyGenerate server routes only
--frontend-onlyGenerate frontend clients only
--docs-onlyGenerate documentation only
--forceBypass input hash cache and always regenerate
--no-cacheRun without reading or writing input hash cache

See Enforceable Guardrails for gate details and CI configuration.

deps

Analyze module dependencies.

OptionDescription
-c, --config <path>Path to config file
-m, --module <name>Module to analyze
--graphOutput dependency graph (Mermaid)
--impact <ref>Analyze impact of changing a specific API
--who-depends-on <ref>Find modules that depend on a specific API
--validateValidate dependencies against OpenAPI declarations

guardrails-init

Create a guardrails.yaml configuration file.

OptionDescription
-o, --output <path>Output path (default: guardrails.yaml)

manifest

Generate or verify manifest for generated artifacts.

OptionDescription
-d, --dir <path>Directory to scan (default: packages/)
--verifyVerify existing manifest
-o, --output <path>Output manifest path

Generated Code

Service Interface

// packages/contract/core/services/UserServiceApi.ts
export interface UserServiceApi {
  getUsers(input: UserService_getUsersInput): Promise<UserListResponse>;
  getUserById(input: UserService_getUserByIdInput): Promise<User>;
}

Service Implementation

// server/src/core/services/UserService.ts
import type { UserServiceApi } from '@project/contract/core/services/UserServiceApi.js';

export class UserService implements UserServiceApi {
  async getUsers(input) {
    // Input is HTTP-agnostic: { limit?: number, offset?: number }
    return { users: [...], total: 100 };
  }
}
DocumentDescription
ExamplesComplete working project with multiple modules, overlays, and cross-module dependencies
Screen SpecFrontend screen contracts — ViewModel, navigation, analytics events in OpenAPI
OpenAPI Overlays (Deep Dive)Complete overlay examples, JSONPath patterns, template context
Enforceable Guardrails (AI-ready)CI integration, security checks, allowlist configuration

Comparison with Similar Tools

Aspectmicro-contractsOpenAPI Generatorts-rest
Primary focusContract governance (server + frontend + CI)Multi-language SDK generationTypeScript-first contract
SSoTOpenAPIOpenAPITypeScript
Multi-artifact generation✅ contract + routes + clients△ SDK-focused (different goal)✅ Strong client/server alignment
Enforceable guardrails✅ Built-in (drift, no direct edit, CI gates)❌ Requires separate design❌ Requires separate design
Public API governancecontract-published + fail-fast❌ Manual❌ N/A
Module dependenciesx-micro-contracts-depend-on + deps/❌ Manual❌ Manual
Cross-cutting concerns✅ OpenAPI Overlays❌ Manual△ Code-level implementation

License

MIT

Keywords

openapi

FAQs

Package last updated on 09 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts