@eventcatalog/linter
Version:
A linter for EventCatalog to validate frontmatter and resource references
780 lines (602 loc) โข 19.9 kB
Markdown
# 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.
[](https://badge.fury.io/js/eventcatalog-linter)
[](https://opensource.org/licenses/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)
```bash
npx @eventcatalog/linter
```
### Global Installation
```bash
npm install -g @eventcatalog/linter
```
### Add to your project
```bash
npm install --save-dev @eventcatalog/linter
```
### Quick Start
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
```
## ๐ ๏ธ Usage
### Basic Usage
Run the linter in your EventCatalog directory:
```bash
# 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:
```json
{
"scripts": {
"lint:eventcatalog": "eventcatalog-linter",
"lint:eventcatalog:verbose": "eventcatalog-linter --verbose"
}
}
```
### CI/CD Integration
#### 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
### Configuration File
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',
},
},
],
};
```
### 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
```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',
},
},
],
};
```
### Using with CI/CD
The configuration file allows you to have different validation rules for different environments:
```bash
# 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:
```bash
# 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
```bash
$ eventcatalog-linter
โ No problems found!
42 files checked
```
### โ Error Output
```bash
$ 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
```bash
$ 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
```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:
### Supported Version Patterns
#### 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
```
### Common Validation Errors
#### โ 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:
### 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
```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
### Setup
```bash
git clone https://github.com/event-catalog/eventcatalog-linter
cd eventcatalog-linter
npm install
```
### Available Scripts
```bash
# 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
```bash
# 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](CONTRIBUTING.md) 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](LICENSE) file for details.
## ๐ Support
- ๐ [EventCatalog Documentation](https://eventcatalog.dev)
- ๐ [Report Issues](https://github.com/event-catalog/eventcatalog-linter/issues)
- ๐ฌ [Discussions](https://github.com/event-catalog/eventcatalog-linter/discussions)
## ๐ Acknowledgments
- Built for the [EventCatalog](https://eventcatalog.dev) community
- Powered by [Zod](https://zod.dev) for schema validation
- Tested with [Vitest](https://vitest.dev)