UNPKG

@eventcatalog/linter

Version:

A linter for EventCatalog to validate frontmatter and resource references

780 lines (602 loc) โ€ข 19.9 kB
# 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](https://badge.fury.io/js/eventcatalog-linter.svg)](https://badge.fury.io/js/eventcatalog-linter) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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)