Skip to content

A linter for EventCatalog to validate frontmatter and resource references

Notifications You must be signed in to change notification settings

event-catalog/linter

Repository files navigation

EventCatalog Linter

A comprehensive linter for EventCatalog that validates frontmatter schemas and resource references to ensure your event-driven architecture documentation is correct and consistent.

npm version License: MIT

🚀 Features

  • 📋 Schema Validation: Validates all resource frontmatter against defined schemas using Zod
  • 🔗 Reference Validation: Ensures all referenced resources (services, events, domains, etc.) actually exist
  • 📦 Semver Version Support: Supports semantic versions, ranges (^1.0.0, ~1.2.0), x-patterns (0.0.x), and latest
  • ⚙️ Configurable Rules: Optional .eventcatalogrc.js config file for customizing rule severity and behavior
  • 🚫 Ignore Patterns: Skip validation for specific file patterns (archived, drafts, etc.)
  • 🎯 Rule Overrides: Apply different rules to different file patterns for flexible team workflows
  • 🎯 Comprehensive Coverage: Supports all EventCatalog resource types
  • ⚡ Fast Performance: Efficiently scans large catalogs
  • 🎨 ESLint-Inspired Output: Clean, file-grouped error reporting with severity levels
  • ⚠️ Warnings Support: Distinguish between errors and warnings with --fail-on-warning option
  • 🧪 Well Tested: Comprehensive test suite with 100% coverage

Supported Resource Types

  • 🏢 Domains (including subdomains)
  • ⚙️ Services
  • 📨 Events
  • 📤 Commands
  • Queries
  • 📡 Channels
  • 🔄 Flows
  • 📊 Entities
  • 👤 Users
  • 👥 Teams

📦 Installation

Use with npx (Recommended)

npx @eventcatalog/linter

Global Installation

npm install -g @eventcatalog/linter

Add to your project

npm install --save-dev @eventcatalog/linter

Quick Start

  1. Install and run: Start linting immediately with npx

    npx @eventcatalog/linter
  2. Add configuration: Create a .eventcatalogrc.js file to customize rules

    module.exports = {
      rules: {
        'best-practices/summary-required': 'warn',
        'refs/owner-exists': 'error',
      },
    };
  3. Integrate with CI/CD: Add to your GitHub Actions or GitLab CI

    - run: npx @eventcatalog/linter

🛠️ Usage

Basic Usage

Run the linter in your EventCatalog directory:

# Lint current directory
eventcatalog-linter

# Lint specific directory
eventcatalog-linter ./my-eventcatalog

# Verbose output with detailed information
eventcatalog-linter --verbose

# Show help
eventcatalog-linter --help

CLI Options

Usage: eventcatalog-linter [options] [directory]

Arguments:
  directory              EventCatalog directory to lint (default: ".")

Options:
  -V, --version          output the version number
  -v, --verbose          Show verbose output (default: false)
  --fail-on-warning      Exit with non-zero code on warnings (default: false)
  -h, --help             display help for command

Package.json Integration

Add to your package.json scripts:

{
  "scripts": {
    "lint:eventcatalog": "eventcatalog-linter",
    "lint:eventcatalog:verbose": "eventcatalog-linter --verbose"
  }
}

CI/CD Integration

GitHub Actions

name: EventCatalog Lint
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npx @eventcatalog/linter

GitLab CI

eventcatalog-lint:
  stage: test
  image: node:18
  script:
    - npx @eventcatalog/linter

⚙️ Configuration

The EventCatalog Linter supports optional configuration through a .eventcatalogrc.js file in your catalog root directory. This allows you to:

  • Turn rules on/off
  • Configure rule severity levels (error, warn, off)
  • Ignore specific file patterns
  • Override rules for specific file patterns

Configuration File

Create a .eventcatalogrc.js file in your EventCatalog root directory:

// .eventcatalogrc.js
module.exports = {
  rules: {
    // Schema validation rules
    'schema/required-fields': 'error',
    'schema/valid-semver': 'error',
    'schema/valid-email': 'warn',

    // Reference validation rules
    'refs/owner-exists': 'error',
    'refs/valid-version-range': 'error',

    // Best practice rules
    'best-practices/summary-required': 'warn',
    'best-practices/owner-required': 'error',
  },

  // Ignore certain paths
  ignorePatterns: ['**/archived/**', '**/drafts/**'],

  // Override rules for specific file patterns
  overrides: [
    {
      files: ['**/experimental/**'],
      rules: {
        'best-practices/owner-required': 'off',
      },
    },
  ],
};

Rule Severity Levels

  • 'error' - Causes the linter to exit with error code 1
  • 'warn' - Shows warnings but allows the linter to pass (unless --fail-on-warning is used)
  • 'off' - Disables the rule completely

Available Rules

Rule Name Description Accepted Values Default
Schema Validation Rules
schema/required-fields Validates that required fields are present in frontmatter error, warn, off error
schema/valid-type Validates that field types are correct (strings, arrays, objects) error, warn, off error
schema/valid-semver Validates semantic version format (1.0.0, 2.1.3-beta) error, warn, off error
schema/valid-email Validates email address format in user frontmatter error, warn, off error
schema/validation-error General schema validation errors error, warn, off error
Reference Validation Rules
refs/owner-exists Ensures referenced owners (users/teams) exist error, warn, off error
refs/valid-version-range Validates version references and patterns error, warn, off error
refs/resource-exists Ensures referenced resources exist (always enabled for critical resources) Always enabled Always enabled
Best Practice Rules
best-practices/summary-required Requires summary field for better documentation error, warn, off error
best-practices/owner-required Requires at least one owner for accountability error, warn, off error

Note: Core resource reference validation (services, domains, entities) is always enabled and cannot be disabled, ensuring referential integrity of your EventCatalog.

Configuration Examples

Relaxed Configuration for Development

module.exports = {
  rules: {
    'best-practices/summary-required': 'warn',
    'best-practices/owner-required': 'warn',
    'refs/owner-exists': 'warn',
  },
  ignorePatterns: ['**/drafts/**', '**/experimental/**'],
};

Strict Configuration for Production

module.exports = {
  rules: {
    'schema/required-fields': 'error',
    'refs/owner-exists': 'error',
    'best-practices/summary-required': 'error',
    'best-practices/owner-required': 'error',
  },
};

Team-Specific Overrides

module.exports = {
  rules: {
    'best-practices/owner-required': 'error',
    'best-practices/summary-required': 'error',
  },
  overrides: [
    {
      files: ['**/legacy/**'],
      rules: {
        'best-practices/owner-required': 'warn',
        'best-practices/summary-required': 'off',
      },
    },
    {
      files: ['**/critical/**'],
      rules: {
        'best-practices/summary-required': 'error',
        'refs/owner-exists': 'error',
      },
    },
  ],
};

Using with CI/CD

The configuration file allows you to have different validation rules for different environments:

# Development - warnings allowed
npx @eventcatalog/linter

# Production - fail on warnings
npx @eventcatalog/linter --fail-on-warning

Using with CI/CD

The configuration file allows you to have different validation rules for different environments:

# Development - warnings allowed
npx @eventcatalog/linter

# Production - fail on warnings
npx @eventcatalog/linter --fail-on-warning

Default Behavior

If no .eventcatalogrc.js file is found, the linter uses default rules where all validations are set to 'error'. This ensures strict validation out of the box, making it easy to get started with quality documentation practices.

✅ What It Validates

Frontmatter Schema Validation

  • ✅ Required fields are present (id, name, version)
  • ✅ Field types are correct (strings, arrays, objects)
  • ✅ Semantic versions follow proper format (1.0.0, 2.1.3-beta)
  • ✅ Version patterns supported (latest, ^1.0.0, ~1.2.0, 0.0.x)
  • ✅ URLs are valid format
  • ✅ Email addresses are valid format
  • ✅ Enum values are from allowed lists
  • ✅ Nested object structures are correct

Reference Validation

  • ✅ Services referenced in domains exist
  • ✅ Events/Commands/Queries referenced in services exist
  • ✅ Entities referenced in domains/services exist
  • ✅ Users/Teams referenced as owners exist
  • ✅ Flow steps reference existing services/messages
  • ✅ Entity properties reference existing entities
  • ✅ Version-specific references are valid

Example EventCatalog Structure

my-eventcatalog/
├── domains/
│   └── sales/
│       └── index.mdx
├── services/
│   ├── user-service/
│   │   └── index.mdx
│   └── order-service/
│       ├── index.mdx
│       └── 2.0.0/
│           └── index.mdx
├── events/
│   ├── user-created/
│   │   └── index.mdx
│   └── order-placed/
│       └── index.mdx
├── commands/
│   └── create-user/
│       └── index.mdx
├── flows/
│   └── user-registration/
│       └── index.mdx
├── entities/
│   ├── user/
│   │   └── index.mdx
│   └── order/
│       └── index.mdx
├── users/
│   ├── john-doe.mdx
│   └── jane-smith.mdx
└── teams/
    └── platform-team.mdx

📊 Example Output

✅ Success Output

$ eventcatalog-linter

✔ No problems found!

  42 files checked

❌ Error Output

$ eventcatalog-linter

services/user-service/index.mdx
  ✖ error version: Invalid semantic version format [version] (schema/valid-semver)
  ⚠ warning Summary is required for better documentation [summary] (best-practices/summary-required)

✖ 2 problems

domains/sales/index.mdx
  ✖ error Referenced service "order-service" does not exist [services] (refs/resource-exists)

✖ 1 problem

flows/user-registration/index.mdx
  ✖ error Referenced service "notification-service" (version: 2.0.0) does not exist [steps[1].service] (refs/valid-version-range)

✖ 1 problem

✖ 4 problems (3 errors, 1 warning)
  3 files checked

🔍 Verbose Output

$ eventcatalog-linter --verbose

services/user-service/index.mdx
  ✖ error version: Invalid semantic version format [version] (schema/valid-semver)

✖ 1 problem

domains/sales/index.mdx
  ✖ error Referenced service "order-service" does not exist [services] (refs/resource-exists)

✖ 1 problem

✖ 2 problems (2 errors, 0 warnings)
  2 files checked

🧪 Validation Examples

Valid Frontmatter Examples

Domain

---
id: sales
name: Sales Domain
version: 1.0.0
summary: Handles all sales-related operations
owners:
  - sales-team
services:
  - id: order-service
    version: 2.0.0
  - id: payment-service
entities:
  - id: order
  - id: customer
    version: 1.2.0
---

Service

---
id: user-service
name: User Service
version: 2.1.0
summary: Manages user accounts and authentication
owners:
  - platform-team
  - john-doe
sends:
  - id: user-created
    version: 1.0.0
  - id: user-updated
receives:
  - id: create-user
  - id: update-user
entities:
  - id: user
repository:
  language: TypeScript
  url: https://github.com/company/user-service
---

Event

---
id: user-created
name: User Created
version: 1.0.0
summary: Triggered when a new user account is created
owners:
  - platform-team
sidebar:
  badge: POST
  label: User Events
draft: false
deprecated: false
---

Flow

---
id: user-registration
name: User Registration Flow
version: 1.0.0
summary: Complete user registration process
steps:
  - id: step1
    title: User submits registration form
    actor:
      name: User
    next_step: step2
  - id: step2
    title: Validate user data
    service:
      id: user-service
      version: 2.0.0
    next_step: step3
  - id: step3
    title: Send welcome email
    message:
      id: user-created
      version: 1.0.0
---

📦 Version Pattern Support

The linter supports flexible version patterns for resource references, making it easy to work with different versioning strategies:

Supported Version Patterns

Exact Versions

sends:
  - id: user-created
    version: 1.0.0 # Exact semantic version

Latest Version

sends:
  - id: user-created
    version: latest # Always use the latest available version

Semver Ranges

sends:
  - id: user-created
    version: ^1.0.0 # Compatible with 1.x.x (1.0.0, 1.2.3, but not 2.0.0)
  - id: user-updated
    version: ~1.2.0 # Compatible with 1.2.x (1.2.0, 1.2.5, but not 1.3.0)

X-Pattern Matching

sends:
  - id: user-created
    version: 0.0.x # Matches 0.0.1, 0.0.5, 0.0.12, etc.
  - id: order-placed
    version: 1.x # Matches 1.0.0, 1.5.3, 1.99.0, etc.

Real-World Example

---
id: inventory-service
name: Inventory Service
version: 2.1.0
sends:
  - id: OutOfStock
    version: latest # Always use latest version
  - id: GetInventoryList
    version: 0.0.x # Use any 0.0.x version
  - id: StockUpdated
    version: ^1.0.0 # Use compatible 1.x versions
---

Common Validation Errors

❌ Missing Required Fields

---
# Missing 'id' field
name: User Service
version: 1.0.0
---

❌ Invalid Semantic Version

---
id: user-service
name: User Service
version: v1.0 # Should be 1.0.0
---

❌ Invalid Reference

---
id: sales-domain
name: Sales Domain
version: 1.0.0
services:
  - id: non-existent-service # Service doesn't exist
---

❌ Invalid Email Format

---
id: john-doe
name: John Doe
email: invalid-email # Should be [email protected]
---

🏷️ Rule Names and Error Codes

The linter provides descriptive rule names in parentheses to help identify and fix issues quickly. Each error shows the specific rule that was violated:

Schema Validation Rules

  • (schema/required-fields) - Required field is missing
  • (schema/valid-type) - Field has wrong data type
  • (schema/valid-semver) - Invalid semantic version format
  • (schema/valid-email) - Invalid email address format
  • (schema/validation-error) - General schema validation error

Reference Validation Rules

  • (refs/owner-exists) - Referenced owner (user/team) doesn't exist
  • (refs/valid-version-range) - Referenced version doesn't exist or invalid pattern
  • (refs/resource-exists) - Referenced resource doesn't exist

Best Practice Rules

  • (best-practices/summary-required) - Summary field is missing
  • (best-practices/owner-required) - At least one owner is required

Parse Errors

  • (@eventcatalog/parse-error) - YAML/frontmatter parsing error

Example with Rule Names

services/user-service/index.mdx
  ✖ error name: Expected string, but received undefined [name] (schema/valid-type)
  ✖ error version: Invalid semantic version format [version] (schema/valid-semver)
  ✖ error Referenced user/team "missing-owner" does not exist [owners] (refs/owner-exists)
  ✖ error Summary is required for better documentation [summary] (best-practices/summary-required)

✖ 4 problems

⚠️ Warnings Support

The linter can distinguish between errors (which break functionality) and warnings (which suggest improvements):

  • Errors: Critical issues that must be fixed
  • Warnings: Suggestions for better documentation

Use --fail-on-warning to treat warnings as errors in CI/CD pipelines:

# Exit with error code if warnings are found
eventcatalog-linter --fail-on-warning

🔧 Development

Setup

git clone https://github.com/event-catalog/eventcatalog-linter
cd eventcatalog-linter
npm install

Available Scripts

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the project
npm run build

# Run in development mode
npm run dev

# Type checking
npm run typecheck

# Linting
npm run lint

Testing

The linter includes comprehensive tests using Vitest:

  • Schema validation tests - Ensures all Zod schemas work correctly
  • Reference validation tests - Tests cross-reference checking
  • File scanning tests - Tests file discovery and parsing
  • CLI tests - Tests command-line interface
  • Integration tests - End-to-end validation scenarios
# Run all tests
npm test

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

# Run specific test file
npm test schema-validator.test.ts

Project Structure

src/
├── cli/           # Command-line interface
├── config/        # Configuration loading and rule management
├── schemas/       # Zod validation schemas
├── scanner/       # File system scanning
├── parser/        # Frontmatter parsing
├── validators/    # Validation logic (schema, reference, best practices)
├── reporters/     # Error reporting
└── types/         # TypeScript definitions

tests/
├── config.test.ts
├── cli-integration.test.ts
├── schema-validator.test.ts
├── reference-validator.test.ts
├── scanner.test.ts
└── utils/

🤝 Contributing

Contributions are welcome! Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

🙏 Acknowledgments

About

A linter for EventCatalog to validate frontmatter and resource references

Resources

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published

Contributors 2

  •  
  •