Prettier Plugin OpenAPI
A Prettier plugin for formatting OpenAPI/Swagger JSON and YAML files with intelligent key sorting, proper indentation, and support for modular OpenAPI file structures.
Features
- 🎯 OpenAPI/Swagger Support: Formats both JSON and YAML OpenAPI specifications
- 🔄 Smart Key Sorting: Automatically sorts OpenAPI keys in the recommended order
- 📁 Modular File Support: Handles both monolithic and modular OpenAPI file structures
- 🧩 Component Files: Supports individual component files (schemas, parameters, responses, etc.)
- 📝 YAML & JSON: Supports both
.yaml/.ymland.jsonfile formats - 🎨 Consistent Formatting: Applies consistent indentation and line breaks
- 🔌 Vendor Extensions: Programmatic loading of vendor-specific extensions
- ⚡ Fast: Built with performance in mind using modern JavaScript
- 🧪 Comprehensive Testing: 99 tests with 94.62% line coverage
- 🚀 CI/CD Ready: Automated testing, building, and publishing
- 🔒 Strict Validation: Properly rejects non-OpenAPI content
- 📊 High Quality: ESLint, Prettier, and TypeScript for code quality
Installation
npm install --save-dev prettier-plugin-openapi
# or
yarn add --dev prettier-plugin-openapi
# or
bun add --dev prettier-plugin-openapi
Usage
Command Line
# Format a single file
npx prettier --write api.yaml
# Format all OpenAPI files in a directory
npx prettier --write "**/*.{openapi.json,openapi.yaml,swagger.json,swagger.yaml}"
# Format with specific options
npx prettier --write api.yaml --tab-width 4 --print-width 100
Configuration
Add the plugin to your Prettier configuration:
package.json
{
"prettier": {
"plugins": ["prettier-plugin-openapi"]
}
}
.prettierrc
{
"plugins": ["prettier-plugin-openapi"],
"tabWidth": 2,
"printWidth": 80
}
.prettierrc.js
module.exports = {
plugins: ['prettier-plugin-openapi'],
tabWidth: 2,
printWidth: 80,
};
Supported File Extensions
.openapi.json.openapi.yaml.openapi.yml.swagger.json.swagger.yaml.swagger.yml.json(for component files).yaml/.yml(for component files)
Modular File Structure Support
The plugin supports both monolithic and modular OpenAPI file structures:
Monolithic Structure
api.yaml # Single file with everything
Modular Structure
├─ openapi.yaml # Root document
├─ paths/ # Path files
│ ├─ users.yaml
│ ├─ users_{id}.yaml
│ └─ auth_login.yaml
├─ components/ # Component files
│ ├─ schemas/
│ │ ├─ User.yaml
│ │ ├─ UserCreate.yaml
│ │ └─ Error.yaml
│ ├─ parameters/
│ │ ├─ CommonPagination.yaml
│ │ └─ UserId.yaml
│ ├─ responses/
│ │ ├─ ErrorResponse.yaml
│ │ └─ UserResponse.yaml
│ ├─ requestBodies/
│ │ └─ UserCreateBody.yaml
│ ├─ headers/
│ │ └─ RateLimitHeaders.yaml
│ ├─ examples/
│ │ └─ UserExample.yaml
│ ├─ securitySchemes/
│ │ └─ BearerAuth.yaml
│ ├─ links/
│ │ └─ UserCreatedLink.yaml
│ └─ callbacks/
│ └─ NewMessageCallback.yaml
└─ webhooks/ # Webhook files
└─ messageCreated.yaml
Key Sorting
The plugin automatically sorts OpenAPI keys in the recommended order:
Top-level keys:
openapi/swaggerinfoserverspathscomponentssecuritytagsexternalDocs
Info section:
titlesummarydescriptionversiontermsOfServicecontactlicense
Components section:
schemasresponsesparametersexamplesrequestBodiesheaderssecuritySchemeslinkscallbackspathItems
Examples
Monolithic File Structure
Before (unformatted):
paths:
/users:
get:
responses:
'200':
description: OK
components:
schemas:
User:
type: object
openapi: 3.0.0
info:
version: 1.0.0
title: My API
After (formatted):
openapi: 3.0.0
info:
title: My API
version: 1.0.0
paths:
/users:
get:
responses:
'200':
description: OK
components:
schemas:
User:
type: object
Modular File Structure
Root Document (openapi.yaml):
openapi: 3.0.0
info:
title: My API
version: 1.0.0
paths:
$ref: './paths/users.yaml'
components:
schemas:
$ref: './components/schemas/User.yaml'
Component File (components/schemas/User.yaml):
type: object
properties:
id:
type: integer
name:
type: string
required:
- id
- name
Path File (paths/users.yaml):
get:
summary: Get users
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '../components/schemas/User.yaml'
Vendor Extensions
The plugin supports vendor-specific extensions through a programmatic loading system:
Adding Vendor Extensions
- Create a TypeScript file in
src/extensions/vendor/ - Export your extensions using the provided API:
// src/extensions/vendor/my-vendor.ts
import { defineVendorExtensions } from '../index';
export const extensions = defineVendorExtensions({
'top-level': (before, after) => ({
'x-my-custom-field': before('info'),
'x-vendor-metadata': after('externalDocs')
}),
'operation': (before, after) => ({
'x-rate-limit': before('responses'),
'x-cache-ttl': after('deprecated')
})
});
Automatic Discovery
Vendor extensions are automatically discovered and loaded at runtime. No manual imports required!
Development
Setup
# Install dependencies
bun install
# Build the plugin
bun run build
# Run tests
bun test
# Run tests with coverage
bun test --coverage
# Lint code
bun run lint
# Format code
bun run format
Project Structure
src/
index.ts # Main plugin implementation
keys.ts # OpenAPI key definitions
extensions/
index.ts # Extension system
vendor-loader.ts # Automatic vendor loading
vendor/ # Vendor extensions
speakeasy.ts
postman.ts
redoc.ts
test/
plugin.test.ts # Core plugin tests
integration.test.ts # Integration tests
build.test.ts # Build validation tests
coverage.test.ts # Coverage enhancement tests
file-detection.test.ts # File detection tests
key-ordering.test.ts # Key sorting tests
custom-extensions.test.ts # Extension tests
options.test.ts # Configuration tests
simple-ordering.test.ts # Basic ordering tests
vendor.test.ts # Vendor extension tests
setup.ts # Test utilities
.github/
workflows/
ci.yml # Continuous Integration
release.yml # Automated releases
examples/
petstore.yaml # Example OpenAPI file
Test Suite
The project includes a comprehensive test suite with 99 tests covering:
- Core Functionality: Plugin structure, parsing, formatting
- Integration Tests: Real OpenAPI file processing, error handling
- Build Tests: Package validation, TypeScript compilation
- Coverage Tests: Edge cases, error scenarios
- File Detection: OpenAPI file recognition, component files
- Key Ordering: OpenAPI key sorting, custom extensions
- Vendor Extensions: Extension system functionality
- Options: Configuration and formatting options
Coverage: 94.62% line coverage, 95.74% function coverage
CI/CD Pipeline
The project includes automated CI/CD with GitHub Actions:
- Continuous Integration: Tests on Node.js 18, 20, 22 and Bun
- Automated Testing: Linting, type checking, security audits
- Smart Releases: Automatic patch version bumps on main branch updates
- NPM Publishing: Automated publishing with version management
- Quality Gates: All tests must pass before release
Configuration Options
The plugin respects standard Prettier options:
tabWidth: Number of spaces for indentation (default: 2)printWidth: Maximum line length (default: 80)useTabs: Use tabs instead of spaces (default: false)
Advanced Features
File Detection
The plugin intelligently detects OpenAPI files based on:
- Content Structure: Files with OpenAPI-specific keys (
openapi,swagger,components, etc.) - Directory Patterns: Files in OpenAPI-related directories (
components/,paths/,webhooks/) - File Extensions: Standard OpenAPI file extensions
Key Sorting Algorithm
The plugin uses a unified sorting algorithm that:
- Prioritizes Standard Keys: OpenAPI specification keys are sorted first
- Handles Custom Extensions: Vendor extensions are positioned relative to standard keys
- Sorts Unknown Keys: Non-standard keys are sorted alphabetically at the end
- Context-Aware: Different sorting rules for different OpenAPI contexts (operations, schemas, etc.)
Performance Optimizations
- Unified Sorting Function: Single function handles all sorting scenarios
- Lazy Loading: Vendor extensions are loaded only when needed
- Efficient Detection: Fast file type detection with minimal overhead
Quality & Reliability
Comprehensive Testing
- 99 Test Cases: Covering all major functionality
- 94.62% Line Coverage: Extensive test coverage
- 95.74% Function Coverage: Nearly complete function testing
- Edge Case Testing: Malformed files, error scenarios, performance
- Integration Testing: Real-world OpenAPI file processing
Code Quality
- TypeScript: Full type safety and IntelliSense support
- ESLint: Strict linting rules for code quality
- Prettier: Consistent code formatting
- Security Audits: Automated dependency vulnerability scanning
- Performance Testing: Large file handling and memory usage
CI/CD Pipeline
- Automated Testing: Runs on every commit and PR
- Multi-Environment: Tests on Node.js 18, 20, 22 and Bun
- Quality Gates: All tests must pass before merge
- Smart Releases: Automatic patch version management
- NPM Publishing: Automated package publishing with proper versioning
Contributing
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes with proper TypeScript types
- Add tests for new functionality (aim for 90%+ coverage)
- Run the test suite:
bun test bun run lint bun run format - Ensure all tests pass (99 tests, 0 failures)
- Submit a pull request with a clear description
Development Guidelines
- Code Quality: All code must pass ESLint and Prettier checks
- Testing: New features require comprehensive tests
- TypeScript: Use proper types and interfaces
- Documentation: Update README for new features
- CI/CD: All GitHub Actions must pass before merge
Release Process
- Automatic: Patch releases happen automatically on main branch updates
- Manual: Major/minor releases require manual version bumps
- Quality Gates: All tests, linting, and security checks must pass
- NPM Publishing: Automated publishing with proper versioning
License
MIT License - see LICENSE file for details.
Related Projects
- Prettier - The core formatter
- OpenAPI Specification - The OpenAPI specification
- Swagger - API development tools