A linter for EventCatalog to validate frontmatter and resource references
npm install @eventcatalog/linterA comprehensive linter for EventCatalog that validates frontmatter schemas and resource references to ensure your event-driven architecture documentation is correct and consistent.


- ๐ 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
- ๐ข Domains (including subdomains)
- โ๏ธ Services
- ๐จ Events
- ๐ค Commands
- โ Queries
- ๐ก Channels
- ๐ Flows
- ๐ Entities
- ๐ค Users
- ๐ฅ Teams
``bash`
npx @eventcatalog/linter
`bash`
npm install -g @eventcatalog/linter
`bash`
npm install --save-dev @eventcatalog/linter
1. Install and run: Start linting immediately with npx
`bash`
npx @eventcatalog/linter
2. Add configuration: Create a .eventcatalogrc.js file to customize rules
`javascript`
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
`yaml`
- run: npx @eventcatalog/linter
Run the linter in your EventCatalog directory:
`bashLint current directory
eventcatalog-linter
$3
`
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
`$3
Add to your
package.json scripts:`json
{
"scripts": {
"lint:eventcatalog": "eventcatalog-linter",
"lint:eventcatalog:verbose": "eventcatalog-linter --verbose"
}
}
`$3
#### GitHub Actions
`yaml
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
`yaml
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
$3
Create a
.eventcatalogrc.js file in your EventCatalog root directory:`javascript
// .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',
},
},
],
};
`$3
-
'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$3
| 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.
$3
#### Relaxed Configuration for Development
`javascript
module.exports = {
rules: {
'best-practices/summary-required': 'warn',
'best-practices/owner-required': 'warn',
'refs/owner-exists': 'warn',
},
ignorePatterns: ['/drafts/', '/experimental/'],
};
`#### Strict Configuration for Production
`javascript
module.exports = {
rules: {
'schema/required-fields': 'error',
'refs/owner-exists': 'error',
'best-practices/summary-required': 'error',
'best-practices/owner-required': 'error',
},
};
`#### Team-Specific Overrides
`javascript
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',
},
},
],
};
`$3
The configuration file allows you to have different validation rules for different environments:
`bash
Development - warnings allowed
npx @eventcatalog/linterProduction - fail on warnings
npx @eventcatalog/linter --fail-on-warning
`$3
The configuration file allows you to have different validation rules for different environments:
`bash
Development - warnings allowed
npx @eventcatalog/linterProduction - fail on warnings
npx @eventcatalog/linter --fail-on-warning
`$3
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
$3
- โ
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$3
- โ
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
$3
`
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
$3
`bash
$ eventcatalog-linterโ No problems found!
42 files checked
`$3
`bash
$ eventcatalog-linterservices/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
`$3
`bash
$ eventcatalog-linter --verboseservices/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
$3
#### Domain
`yaml
---
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
`yaml
---
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
`yaml
---
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
`yaml
---
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:
$3
#### Exact Versions
`yaml
sends:
- id: user-created
version: 1.0.0 # Exact semantic version
`#### Latest Version
`yaml
sends:
- id: user-created
version: latest # Always use the latest available version
`#### Semver Ranges
`yaml
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
`yaml
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
`yaml
---
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
---
`$3
#### โ Missing Required Fields
`yaml
---
Missing 'id' field
name: User Service
version: 1.0.0
---
`#### โ Invalid Semantic Version
`yaml
---
id: user-service
name: User Service
version: v1.0 # Should be 1.0.0
---
`#### โ Invalid Reference
`yaml
---
id: sales-domain
name: Sales Domain
version: 1.0.0
services:
- id: non-existent-service # Service doesn't exist
---
`#### โ Invalid Email Format
`yaml
---
id: john-doe
name: John Doe
email: invalid-email # Should be john@example.com
---
`๐ท๏ธ 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:
$3
-
(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$3
-
(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$3
-
(best-practices/summary-required) - Summary field is missing
- (best-practices/owner-required) - At least one owner is required$3
-
(@eventcatalog/parse-error) - YAML/frontmatter parsing error$3
`bash
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:`bash
Exit with error code if warnings are found
eventcatalog-linter --fail-on-warning
`๐ง Development
$3
`bash
git clone https://github.com/event-catalog/eventcatalog-linter
cd eventcatalog-linter
npm install
`$3
`bash
Run tests
npm testRun tests in watch mode
npm run test:watchBuild the project
npm run buildRun in development mode
npm run devType checking
npm run typecheckLinting
npm run lint
`$3
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
`bash
Run all tests
npm testRun tests with coverage
npm test -- --coverageRun specific test file
npm test schema-validator.test.ts
`$3
`
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 definitionstests/
โโโ 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`)This project is licensed under the MIT License - see the LICENSE file for details.
- ๐ EventCatalog Documentation
- ๐ Report Issues
- ๐ฌ Discussions
- Built for the EventCatalog community
- Powered by Zod for schema validation
- Tested with Vitest