{"id":28892860,"url":"https://github.com/developerkunal/openmorph","last_synced_at":"2026-05-05T00:33:43.788Z","repository":{"id":298834404,"uuid":"1001272656","full_name":"developerkunal/OpenMorph","owner":"developerkunal","description":"OpenMorph: Modern CLI \u0026 TUI for safe, interactive OpenAPI vendor extension key transforms with colorized diffs, dry-run, and config merging.","archived":false,"fork":false,"pushed_at":"2025-06-20T16:37:04.000Z","size":2635,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-20T17:39:47.389Z","etag":null,"topics":["api-tools","automation","cli-tool","developer","devops","devops-tools","fern","golang","interactive-cli","json","openapi","pagination","schema-validation","speakeasy","transformation","tui","vendor-extensions","yaml"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/developerkunal.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-13T05:32:39.000Z","updated_at":"2025-06-20T16:35:00.000Z","dependencies_parsed_at":"2025-06-20T17:29:27.454Z","dependency_job_id":null,"html_url":"https://github.com/developerkunal/OpenMorph","commit_stats":null,"previous_names":["developerkunal/openmorph"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/developerkunal/OpenMorph","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developerkunal%2FOpenMorph","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developerkunal%2FOpenMorph/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developerkunal%2FOpenMorph/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developerkunal%2FOpenMorph/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/developerkunal","download_url":"https://codeload.github.com/developerkunal/OpenMorph/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/developerkunal%2FOpenMorph/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261050699,"owners_count":23102557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-tools","automation","cli-tool","developer","devops","devops-tools","fern","golang","interactive-cli","json","openapi","pagination","schema-validation","speakeasy","transformation","tui","vendor-extensions","yaml"],"created_at":"2025-06-21T02:06:51.934Z","updated_at":"2026-05-05T00:33:43.779Z","avatar_url":"https://github.com/developerkunal.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenMorph\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/developerkunal/OpenMorph/main/.github/openmorph_darkmode.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/developerkunal/OpenMorph/main/.github/openmorph_lightmode.png\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/developerkunal/OpenMorph/main/.github/openmorph_lightmode.png\" alt=\"OpenMorph Logo\" width=\"180\"/\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/developerkunal/OpenMorph.svg)](https://pkg.go.dev/github.com/developerkunal/OpenMorph)\n[![CI](https://github.com/developerkunal/OpenMorph/actions/workflows/ci.yml/badge.svg)](https://github.com/developerkunal/OpenMorph/actions/workflows/ci.yml)\n[![Security](https://github.com/developerkunal/OpenMorph/actions/workflows/security.yml/badge.svg)](https://github.com/developerkunal/OpenMorph/actions/workflows/security.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/developerkunal/OpenMorph)](https://goreportcard.com/report/github.com/developerkunal/OpenMorph)\n[![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/developerkunal/OpenMorph)\n---\n\nOpenMorph is a production-grade CLI and TUI tool for transforming OpenAPI vendor extension keys across YAML/JSON files. It supports interactive review, dry-run previews, backups, robust mapping/exclusion logic, vendor-specific pagination extensions, and is designed for maintainability and extensibility.\n\n## Features\n\n- Transform OpenAPI vendor extension keys in YAML/JSON\n- **Unified transformation pipeline** - Orchestrates all transformations in optimal order for consistent results\n- **Single file and directory processing** - Support for transforming individual files or entire directories\n- **Output file support** - Transform to new files while preserving originals, configurable via CLI or config file\n- **Default values injection** - Automatically set default values for parameters, schemas, and responses with rule-based matching\n- **Vendor-specific pagination extensions** - Auto-inject Fern, Speakeasy, and other vendor pagination metadata\n- **Auto-detection of array fields** - Automatically find results arrays in response schemas\n- **Response flattening** - Simplify oneOf/anyOf/allOf structures with single references\n- Interactive TUI for reviewing and approving changes\n- Colorized before/after diffs (CLI and TUI)\n- Dry-run mode for safe previews\n- Backup support\n- Config file and CLI flag merging\n- Exclude keys from transformation\n- OpenAPI validation integration\n- **Pagination priority support** - Remove lower-priority pagination strategies\n- **Endpoint-specific configuration** - Apply different rules to specific API endpoints\n- **Consistent JSON formatting** - Maintains clean, multi-line array formatting\n- Modern, maintainable Go codebase\n\n## Credits / Acknowledgements\n\n- [Bubble Tea](https://github.com/charmbracelet/bubbletea) for TUI\n- [spf13/cobra](https://github.com/spf13/cobra) for CLI\n- [gopkg.in/yaml.v3](https://github.com/go-yaml/yaml) for YAML parsing\n- [Contributor Covenant](https://www.contributor-covenant.org/) for Code of Conduct\n\n## Installation\n\n### Docker (Recommended for CI/CD)\n\n#### Quick Start with Docker\n\n```bash\n# Pull the latest image (automatically selects correct architecture)\ndocker pull ghcr.io/developerkunal/openmorph:latest\n\n# Transform files in current directory\ndocker run --rm -v $(pwd):/workspace ghcr.io/developerkunal/openmorph:latest \\\n  --input /workspace --dry-run\n\n# Use with configuration file\ndocker run --rm -v $(pwd):/workspace ghcr.io/developerkunal/openmorph:latest \\\n  --config /workspace/openmorph.yaml --input /workspace\n```\n\n#### Docker Images Available\n\n**Production Images (Multi-platform: linux/amd64, linux/arm64):**\n\n- `ghcr.io/developerkunal/openmorph:latest` - Latest release (auto-selects platform)\n- `ghcr.io/developerkunal/openmorph:v1.0.0` - Specific version (auto-selects platform)\n- `ghcr.io/developerkunal/openmorph:v1.0` - Latest patch in v1.0.x\n- `ghcr.io/developerkunal/openmorph:v1` - Latest minor in v1.x.x\n\n**Specialized Images:**\n\n- `ghcr.io/developerkunal/openmorph:v1.0.0-distroless` - Enhanced security (~15MB)\n- `ghcr.io/developerkunal/openmorph:dev` - Development with shell access (~50MB)\n\n📖 **See [DOCKER.md](DOCKER.md) for comprehensive Docker usage guide and CI/CD integration examples.**\n\n### Package Managers\n\n#### Homebrew (macOS/Linux)\n\n```bash\n# Install directly (recommended)\nbrew install developerkunal/openmorph/openmorph\n\n# Or add tap first, then install\nbrew tap developerkunal/openmorph\nbrew install openmorph\n\n# Verify installation\nopenmorph --version\n```\n\n#### Scoop (Windows)\n\n```powershell\n# Add the bucket and install\nscoop bucket add openmorph https://github.com/developerkunal/scoop-openmorph.git\nscoop install openmorph\n\n# Verify installation\nopenmorph --version\n```\n\n### Direct Download\n\nDownload pre-built binaries from [GitHub Releases](https://github.com/developerkunal/OpenMorph/releases):\n\n```bash\n# Linux/macOS example\ncurl -L -o openmorph.tar.gz \\\n  https://github.com/developerkunal/OpenMorph/releases/download/v1.0.0/openmorph_1.0.0_linux_amd64.tar.gz\ntar -xzf openmorph.tar.gz\n./openmorph --version\n```\n\n### From Source\n\n#### Prerequisites\n\n- Go 1.24 or later\n\n#### Build from source\n\n```bash\n# Clone the repository\ngit clone https://github.com/developerkunal/OpenMorph.git\ncd OpenMorph\n\n# Build the binary\nmake build\n# or\ngo build -o openmorph main.go\n```\n\n#### Install from source\n\n```bash\n# Build and install to GOPATH/bin\nmake install\n```\n\n## Usage\n\n```sh\nopenmorph [flags]\n```\n\n### Flags and Options\n\n| Flag                    | Description                                                                            |\n| ----------------------- | -------------------------------------------------------------------------------------- |\n| `--input`               | Path to the input directory or file (YAML/JSON). Required.                             |\n| `--output`              | Output file path for single file transformations (optional).                           |\n| `--mapping`             | Key mapping(s) in the form `old=new`. Can be specified multiple times.                 |\n| `--exclude`             | Key(s) to exclude from transformation. Can be specified multiple times.                |\n| `--dry-run`             | Show a preview of changes (with colorized before/after diffs) without modifying files. |\n| `--backup`              | Create `.bak` backup files before modifying originals.                                 |\n| `--interactive`         | Launch an interactive TUI for reviewing and approving changes before applying them.    |\n| `--config`              | Path to a YAML/JSON config file with mappings/excludes.                                |\n| `--no-config`           | Ignore all config files and use only CLI flags.                                        |\n| `--validate`            | Run OpenAPI validation (requires `swagger-cli` in PATH).                               |\n| `--pagination-priority` | Pagination strategy priority order (e.g., checkpoint,offset,page,cursor,none).         |\n| `--vendor-providers`    | Specific vendor providers to apply (e.g., fern,speakeasy). If empty, applies all.      |\n| `--flatten-responses`   | Flatten oneOf/anyOf/allOf with single $ref after pagination processing.                |\n| `--version`             | Show version and exit.                                                                 |\n| `-h`, `--help`          | Show help message.                                                                     |\n\n### Example: Basic CLI Usage\n\nTransform all `x-foo` keys to `x-bar` in a directory:\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar\n```\n\n### Example: Exclude Keys\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar --exclude x-ignore\n```\n\n### Example: Dry Run (Preview Only)\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar --dry-run\n```\n\n**Note:** In dry-run mode, transformations (pagination and response flattening) are previewed independently based on the original file. In actual execution, they are applied sequentially, so later steps may show different results. Use `--interactive` mode to see the exact cumulative effects of all transformations.\n\n### Example: Interactive Review (TUI)\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar --interactive\n```\n\n### Example: Using a Config File\n\n```sh\nopenmorph --config ./morph.yaml\n```\n\n### Example: Single File Output\n\nTransform a single OpenAPI file and save to a new location:\n\n```sh\nopenmorph --input ./api.yaml --output ./transformed-api.yaml --mapping x-foo=x-bar\n```\n\n### Example: Output via Config File\n\n```sh\nopenmorph --config ./morph.yaml\n```\n\nWhere `morph.yaml` contains both input and output:\n\n```yaml\ninput: ./api.yaml\noutput: ./transformed-api.yaml\nmappings:\n  x-foo: x-bar\n  x-baz: x-qux\n```\n\n#### Example morph.yaml\n\n```yaml\ninput: ./openapi\noutput: ./transformed # Optional: for single file transformations\nmappings:\n  x-foo: x-bar\n  x-baz: x-qux\nexclude:\n  - x-ignore\npagination_priority:\n  - checkpoint\n  - offset\n  - page\n  - cursor\n  - none\nvendor_extensions:\n  enabled: true\n  providers:\n    fern:\n      extension_name: \"x-fern-pagination\"\n      target_level: \"operation\"\n      methods: [\"get\"]\n      field_mapping:\n        request_params:\n          cursor: [\"cursor\", \"after\"]\n          limit: [\"limit\", \"size\"]\n      strategies:\n        cursor:\n          template:\n            type: \"cursor\"\n            cursor_param: \"$request.{cursor_param}\"\n            page_size_param: \"$request.{limit_param}\"\n            results_path: \"$response.{results_field}\"\n          required_fields: [\"cursor_param\", \"results_field\"]\n```\n\n### Example: With Backup\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar --backup\n```\n\n### Example: Validate After Transform\n\n```sh\nopenmorph --input ./openapi --mapping x-foo=x-bar --validate\n```\n\n### Example: Add Vendor Extensions\n\nAdd vendor extensions (auto-enabled when configured):\n\n```sh\nopenmorph --input ./openapi --config fern-config.yaml\n```\n\nAdd extensions for specific providers only:\n\n```sh\nopenmorph --input ./openapi --vendor-providers fern --config config.yaml\n```\n\n### Example: Complete Transformation\n\nTransform keys, clean up pagination, add vendor extensions, and set default values:\n\n```sh\nopenmorph --input ./openapi \\\n  --mapping x-operation-group-name=x-fern-sdk-group-name \\\n  --pagination-priority cursor,offset,none \\\n  --vendor-providers fern \\\n  --flatten-responses \\\n  --backup \\\n  --config ./config.yaml\n```\n\nYour `config.yaml` can include all features:\n\n```yaml\nmappings:\n  x-foo: x-bar\nvendor_extensions:\n  enabled: true\n  providers:\n    fern:\n      # ... fern config\ndefault_values:\n  enabled: true\n  rules:\n    # ... default value rules\n```\n\n### Example: Pagination Priority\n\nTransform APIs to use only checkpoint pagination (highest priority):\n\n```sh\nopenmorph --input ./openapi --pagination-priority checkpoint,offset,none\n```\n\nRemove lower-priority pagination strategies and add vendor extensions:\n\n```sh\nopenmorph --input ./openapi \\\n  --pagination-priority cursor,page,offset,none \\\n  --vendor-providers fern \\\n  --config fern-config.yaml \\\n  --dry-run\n```\n\nUse endpoint-specific pagination rules via configuration file:\n\n```sh\nopenmorph --input ./openapi --config my-config.yaml\n```\n\nWhere `my-config.yaml` contains:\n\n```yaml\npagination_priority: [\"checkpoint\", \"offset\", \"page\"]\nendpoint_pagination:\n  - endpoint: \"/api/v1/users\"\n    method: \"GET\"\n    pagination: \"cursor\"\n  - endpoint: \"/api/v1/analytics/*\"\n    method: \"POST\"\n    pagination: \"offset\"\n```\n\n## Pagination Priority\n\nThe pagination priority feature allows you to enforce pagination strategies across your OpenAPI specifications by removing lower-priority pagination parameters and responses. It supports both global priority rules and endpoint-specific overrides.\n\n### How It Works\n\nWhen pagination priority is configured, OpenMorph:\n\n1. **Detects** all pagination strategies in each endpoint (parameters and responses)\n2. **Selects** the highest priority strategy from those available (endpoint-specific rules take precedence)\n3. **Removes** parameters and response schemas belonging to lower-priority strategies\n4. **Preserves** OpenAPI structure integrity (handles `oneOf`, `anyOf`, `allOf`)\n5. **Cleans up** unused component schemas\n\n### Configuration Options\n\n#### Global Pagination Priority\n\nSet a global priority order that applies to all endpoints:\n\n```yaml\npagination_priority: [\"checkpoint\", \"offset\", \"page\", \"cursor\", \"none\"]\n```\n\n#### Endpoint-Specific Pagination Rules\n\nOverride global priority for specific endpoints:\n\n```yaml\npagination_priority: [\"checkpoint\", \"offset\", \"page\"] # Global fallback\nendpoint_pagination:\n  - endpoint: \"/api/v1/users\"\n    method: \"GET\"\n    pagination: \"cursor\"\n  - endpoint: \"/api/v1/posts/*\" # Supports wildcards\n    method: \"POST\"\n    pagination: \"checkpoint\"\n  - endpoint: \"/api/v1/analytics\"\n    method: \"GET\"\n    pagination: \"offset\"\n```\n\n**Endpoint Pattern Matching:**\n\n- **Exact match**: `/api/v1/users` matches only `/api/v1/users`\n- **Suffix wildcard**: `/api/v1/users/*` matches `/api/v1/users`, `/api/v1/users/123`, `/api/v1/users/123/posts`, etc.\n- **Middle wildcard**: `/api/*/analytics` matches `/api/v1/analytics`, `/api/v2/analytics`, etc.\n- **Multiple wildcards**: `/api/*/users/*/posts` matches `/api/v1/users/123/posts`, `/api/v2/users/abc/posts`, etc.\n\n#### Advanced Pattern Examples\n\n```yaml\nendpoint_pagination:\n  # Exact match\n  - endpoint: \"/api/v1/users\"\n    method: \"GET\"\n    pagination: \"offset\"\n\n  # Suffix wildcard - matches all sub-paths\n  - endpoint: \"/api/v1/legacy/*\"\n    method: \"GET\"\n    pagination: \"offset\"\n\n  # Middle wildcard - matches across versions\n  - endpoint: \"/api/*/analytics\"\n    method: \"GET\"\n    pagination: \"cursor\"\n\n  # Multiple wildcards\n  - endpoint: \"/api/*/users/*/profile\"\n    method: \"GET\"\n    pagination: \"none\"\n\n  # Complex patterns\n  - endpoint: \"/tenant/*/api/v*/reports\"\n    method: \"POST\"\n    pagination: \"checkpoint\"\n```\n\n#### Priority Resolution\n\n1. **First**: Check endpoint-specific rules for exact endpoint + method match\n2. **Fallback**: Use global `pagination_priority` if no specific rule matches\n\n### Supported Pagination Strategies\n\n| Strategy   | Parameters                           | Response Fields                          |\n| ---------- | ------------------------------------ | ---------------------------------------- |\n| checkpoint | `from`, `take`, `after`              | `next`, `next_checkpoint`                |\n| offset     | `offset`, `limit`, `include_totals`  | `total`, `offset`, `limit`, `count`      |\n| page       | `page`, `per_page`, `include_totals` | `start`, `limit`, `total`, `total_count` |\n| cursor     | `cursor`, `size`                     | `next_cursor`, `has_more`                |\n| none       | (no parameters)                      | (no fields)                              |\n\n### Example Transformations\n\n#### Global Priority Example\n\n**Configuration:**\n\n```yaml\npagination_priority: [\"checkpoint\", \"offset\"]\n```\n\n**Before** (multiple pagination strategies):\n\n```yaml\n\"/users\":\n  get:\n    parameters:\n      - name: offset\n        in: query\n      - name: from\n        in: query\n    responses:\n      \"200\":\n        content:\n          application/json:\n            schema:\n              oneOf:\n                - properties:\n                    total: { type: integer } # offset\n                    users: { type: array }\n                - properties:\n                    next: { type: string } # checkpoint\n                    users: { type: array }\n```\n\n**After** (checkpoint priority):\n\n```yaml\n\"/users\":\n  get:\n    parameters:\n      - name: from\n        in: query\n    responses:\n      \"200\":\n        content:\n          application/json:\n            schema:\n              properties:\n                next: { type: string }\n                users: { type: array }\n```\n\n#### Endpoint-Specific Override Example\n\n**Configuration:**\n\n```yaml\npagination_priority: [\"checkpoint\", \"offset\"] # Global default\nendpoint_pagination:\n  - endpoint: \"/users\"\n    method: \"GET\"\n    pagination: \"offset\" # Override for this specific endpoint\n```\n\n**Result:** The `/users` GET endpoint will use `offset` pagination (keeping `offset`, `limit`, `include_totals` parameters) while all other endpoints follow the global priority and prefer `checkpoint` pagination.\n\n### Advanced Endpoint-Specific Configuration\n\n#### Complex Pattern Examples\n\n```yaml\npagination_priority: [\"cursor\", \"offset\", \"page\"] # Global fallback\nendpoint_pagination:\n  # Exact match\n  - endpoint: \"/api/v1/users\"\n    method: \"GET\"\n    pagination: \"offset\"\n\n  # Suffix wildcard - matches all sub-paths\n  - endpoint: \"/api/v1/legacy/*\"\n    method: \"GET\"\n    pagination: \"offset\"\n\n  # Middle wildcard - matches across versions\n  - endpoint: \"/api/*/analytics\"\n    method: \"GET\"\n    pagination: \"cursor\"\n\n  # Multiple wildcards\n  - endpoint: \"/api/*/users/*/profile\"\n    method: \"GET\"\n    pagination: \"none\"\n\n  # Complex patterns\n  - endpoint: \"/tenant/*/api/v*/reports\"\n    method: \"POST\"\n    pagination: \"checkpoint\"\n```\n\n#### Rule Ordering and Precedence\n\n**Important**: Rules are evaluated in **order of definition**. The first matching rule wins.\n\n```yaml\nendpoint_pagination:\n  # ❌ WRONG: Broad pattern first\n  - endpoint: \"/api/*\"\n    method: \"GET\"\n    pagination: \"offset\"\n  - endpoint: \"/api/v1/users\" # This will never match!\n    method: \"GET\"\n    pagination: \"cursor\"\n\n  # ✅ CORRECT: Specific patterns first\n  - endpoint: \"/api/v1/users\"\n    method: \"GET\"\n    pagination: \"cursor\"\n  - endpoint: \"/api/*\" # Catches everything else\n    method: \"GET\"\n    pagination: \"offset\"\n```\n\n#### Use Cases and Best Practices\n\n**1. API Versioning Strategy**\n\n```yaml\npagination_priority: [\"cursor\"] # Default for new APIs\nendpoint_pagination:\n  # Legacy v1 API uses offset pagination\n  - endpoint: \"/api/v1/*\"\n    method: \"GET\"\n    pagination: \"offset\"\n\n  # Modern v2+ APIs use cursor pagination (global default applies)\n```\n\n**2. Resource-Specific Requirements**\n\n```yaml\npagination_priority: [\"offset\", \"page\"]\nendpoint_pagination:\n  # Analytics endpoints need cursor for real-time data\n  - endpoint: \"/api/*/analytics\"\n    method: \"GET\"\n    pagination: \"cursor\"\n\n  # Search endpoints work best with page-based pagination\n  - endpoint: \"/api/*/search\"\n    method: \"GET\"\n    pagination: \"page\"\n\n  # Disable pagination for configuration endpoints\n  - endpoint: \"/api/*/config\"\n    method: \"GET\"\n    pagination: \"none\"\n```\n\n**3. Performance Optimization**\n\n```yaml\npagination_priority: [\"offset\"]\nendpoint_pagination:\n  # High-traffic endpoints use cursor for better performance\n  - endpoint: \"/api/v1/feed\"\n    method: \"GET\"\n    pagination: \"cursor\"\n\n  - endpoint: \"/api/v1/notifications\"\n    method: \"GET\"\n    pagination: \"cursor\"\n```\n\n#### Configuration Validation\n\nOpenMorph validates endpoint pagination rules:\n\n- ✅ Valid pagination strategies: `cursor`, `offset`, `page`, `checkpoint`, `none`\n- ✅ Valid HTTP methods: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `TRACE`\n- ✅ Valid endpoint patterns: exact paths or wildcard patterns with `*`\n- ❌ Invalid configurations will show clear error messages\n\n#### CLI Integration\n\n```bash\n# Use endpoint-specific rules from config file\nopenmorph --input ./openapi --config pagination-config.yaml\n\n# Combine with other features\nopenmorph --input ./openapi \\\n  --config pagination-config.yaml \\\n  --vendor-providers fern \\\n  --flatten-responses \\\n  --dry-run\n```\n\n**Example `pagination-config.yaml`:**\n\n```yaml\npagination_priority: [\"cursor\", \"offset\", \"page\", \"none\"]\nendpoint_pagination:\n  - endpoint: \"/api/v1/legacy/*\"\n    method: \"GET\"\n    pagination: \"offset\"\n  - endpoint: \"/api/v2/realtime/*\"\n    method: \"GET\"\n    pagination: \"cursor\"\n  - endpoint: \"/api/admin/*\"\n    method: \"*\"\n    pagination: \"none\"\n\nvendor_extensions:\n  enabled: true\n  providers:\n    fern:\n      extension_name: \"x-fern-pagination\"\n      target_level: \"operation\"\n      methods: [\"get\"]\n```\n\n## Vendor Extensions\n\nOpenMorph provides powerful vendor-specific extension injection capabilities, automatically adding pagination metadata like `x-fern-pagination` to your OpenAPI specifications. The system is provider-agnostic, configurable, and includes intelligent auto-detection of pagination patterns and array fields.\n\n\u003e **📝 Configuration Required**: Vendor extensions are configured via config files only (not CLI flags) due to their complexity. This design ensures maintainability, reusability, and supports advanced features like multiple providers, strategies, and field mappings.\n\n### Key Features\n\n- **Generic \u0026 Extensible** - Provider-agnostic configuration system supporting any vendor\n- **Auto-Detection** - Automatically detects pagination patterns and result array fields\n- **Smart Field Mapping** - Flexible parameter and response field mapping\n- **Template-Based** - Configurable templates for vendor-specific extensions\n- **Format Preservation** - Maintains consistent JSON/YAML formatting\n- **Multi-Strategy Support** - Supports cursor, offset, page, and checkpoint pagination\n- **Config-File Based** - Rich configuration via YAML/JSON for maximum flexibility\n\n### Supported Vendors\n\n- **Fern** - Adds `x-fern-pagination` extensions with full strategy support\n- **Extensible Architecture** - Easy to add Speakeasy, OpenAPI Generator, and other vendors\n\n### How It Works\n\n1. **Scans API Operations** - Analyzes GET endpoints for pagination parameters\n2. **Auto-Detects Strategies** - Identifies cursor, offset, page, and checkpoint patterns\n3. **Finds Result Arrays** - Automatically locates array fields in response schemas (`data`, `items`, `results`, etc.)\n4. **Applies Templates** - Uses configurable templates to generate vendor extensions\n5. **Preserves Structure** - Maintains original OpenAPI formatting and structure\n\n### Configuration\n\nVendor extensions are configured through the config file using the `vendor_extensions` section:\n\n```yaml\nvendor_extensions:\n  enabled: true\n  providers:\n    fern:\n      extension_name: \"x-fern-pagination\"\n      target_level: \"operation\" # operation | path | global\n      methods: [\"get\"] # HTTP methods to process\n      field_mapping:\n        request_params:\n          cursor: [\"cursor\", \"next_cursor\", \"after\"]\n          limit: [\"limit\", \"size\", \"page_size\", \"per_page\", \"take\"]\n          offset: [\"offset\", \"skip\"]\n          page: [\"page\", \"page_number\"]\n          # results field mapping not needed - auto-detected!\n      strategies:\n        cursor:\n          template:\n            type: \"cursor\"\n            cursor_param: \"$request.{cursor_param}\"\n            page_size_param: \"$request.{limit_param}\"\n            results_path: \"$response.{results_field}\"\n          required_fields: [\"cursor_param\", \"results_field\"]\n        offset:\n          template:\n            type: \"offset\"\n            offset_param: \"$request.{offset_param}\"\n            limit_param: \"$request.{limit_param}\"\n            results_path: \"$response.{results_field}\"\n          required_fields: [\"offset_param\", \"results_field\"]\n        page:\n          template:\n            type: \"page\"\n            page_param: \"$request.{page_param}\"\n            page_size_param: \"$request.{limit_param}\"\n            results_path: \"$response.{results_field}\"\n          required_fields: [\"page_param\", \"results_field\"]\n        checkpoint:\n          template:\n            type: \"checkpoint\"\n            cursor_param: \"$request.{cursor_param}\"\n            page_size_param: \"$request.{limit_param}\"\n            results_path: \"$response.{results_field}\"\n          required_fields: [\"cursor_param\", \"results_field\"]\n```\n\n### Usage Examples\n\n**Add vendor extensions to all APIs:**\n\n```sh\nopenmorph --input ./openapi --config config.yaml\n```\n\n**Add extensions for specific providers only:**\n\n```sh\nopenmorph --input ./openapi --vendor-providers fern --config config.yaml\n```\n\n**Combine with other transformations:**\n\n```sh\nopenmorph --input ./openapi \\\n  --mapping x-operation-group-name=x-fern-sdk-group-name \\\n  --vendor-providers fern \\\n  --pagination-priority cursor,offset,none \\\n  --flatten-responses \\\n  --backup \\\n  --config config.yaml\n```\n\n**Preview changes with dry-run:**\n\n```sh\nopenmorph --input ./openapi --dry-run --config config.yaml\n```\n\n\u003e **💡 Pro Tip**: Vendor extensions auto-enable when configured in your config file. The `--vendor-providers` flag filters which providers from your config are applied, allowing you to test specific vendors without modifying your config file.\n\n### Auto-Detection Features\n\n**Array Field Detection**: Automatically finds array fields in response schemas:\n\n- `data`, `items`, `results`, `users`, `products`, etc.\n- Works with complex schemas including `$ref`, `oneOf`, `anyOf`, `allOf`\n- No manual configuration required!\n\n**Parameter Mapping**: Maps request parameters to template variables:\n\n- `cursor` → `$request.cursor`\n- `limit` → `$request.limit`\n- `page` → `$request.page`\n\n### Example Output\n\n**Before:**\n\n```yaml\n/users:\n  get:\n    parameters:\n      - name: cursor\n        in: query\n      - name: size\n        in: query\n    responses:\n      \"200\":\n        content:\n          application/json:\n            schema:\n              properties:\n                data:\n                  type: array\n                  items: { type: object }\n```\n\n**After:**\n\n```yaml\n/users:\n  get:\n    parameters:\n      - name: cursor\n        in: query\n      - name: size\n        in: query\n    responses:\n      \"200\":\n        content:\n          application/json:\n            schema:\n              properties:\n                data:\n                  type: array\n                  items: { type: object }\n    x-fern-pagination:\n      type: \"cursor\"\n      cursor_param: \"$request.cursor\"\n      page_size_param: \"$request.size\"\n      results_path: \"$response.data\"\n```\n\n## Default Values\n\nOpenMorph includes a powerful default values feature that allows you to automatically set default values throughout your OpenAPI specifications. This feature supports complex rule-based matching and can be applied to parameters, request bodies, response schemas, and component schemas.\n\n### Overview\n\nThe Default Values feature allows you to:\n\n- Set defaults for **parameter schemas** (path, query, header, cookie)\n- Set defaults for **request body schemas**\n- Set defaults for **response schemas**\n- Set defaults for **component schemas** (reusable objects)\n- Apply defaults to **arrays** and **enum fields**\n- Use **regex patterns** for flexible property matching\n- Configure **rule priorities** for precise control\n\n### Configuration\n\nDefault values are configured through the `default_values` section in your config file:\n\n```yaml\ndefault_values:\n  enabled: true\n  rules:\n    # Set default limit for pagination parameters\n    query_limit_defaults:\n      target:\n        location: \"parameter\"\n      condition:\n        parameter_in: \"query\"\n        type: \"integer\"\n        property_name: \"(limit|size|page_size|per_page)\"\n      value: 20\n      priority: 10\n\n    # Set default sort direction\n    query_sort_defaults:\n      target:\n        location: \"parameter\"\n      condition:\n        parameter_in: \"query\"\n        type: \"string\"\n        property_name: \"(sort|order|direction)\"\n      value: \"asc\"\n      priority: 9\n\n    # Boolean fields default to true\n    boolean_defaults:\n      target:\n        location: \"component\"\n      condition:\n        type: \"boolean\"\n        property_name: \"(active|enabled|is_.*)\"\n      value: true\n      priority: 8\n```\n\n### Configuration Options\n\n#### Target\n\n- `location`: Where to apply defaults\n  - `\"parameter\"` - URL parameters (query, path, header, cookie)\n  - `\"request_body\"` - Request body schemas\n  - `\"response\"` - Response body schemas\n  - `\"component\"` - Component schemas (reusable objects)\n- `property`: Optional specific property name to target\n- `path`: Optional JSONPath-like selector for precise targeting\n\n#### Conditions\n\n- `type`: Schema type constraint (`\"string\"`, `\"integer\"`, `\"boolean\"`, `\"array\"`, `\"object\"`)\n- `parameter_in`: For parameters - where they're located (`\"query\"`, `\"path\"`, `\"header\"`, `\"cookie\"`)\n- `http_methods`: List of HTTP methods to target (`[\"get\", \"post\"]`)\n- `path_patterns`: List of regex patterns for API paths (`[\"/api/v1/.*\"]`)\n- `has_enum`: Only apply to fields with enum constraints\n- `is_array`: Only apply to array-type fields\n- `property_name`: Regex pattern to match property names (`\"(limit|size|page_size)\"`)\n- `required`: Apply only to required (`true`) or optional (`false`) fields\n\n#### Values\n\n- `value`: Simple default value (string, number, boolean, array, object)\n- `template`: Complex template object for structured defaults\n- `priority`: Rule priority (higher numbers = higher priority)\n\n### Usage Examples\n\n**Apply defaults using config file:**\n\n```bash\nopenmorph --input ./openapi --config config.yaml\n```\n\n**Preview defaults changes:**\n\n```bash\nopenmorph --input ./openapi --config config.yaml --dry-run\n```\n\n**Combine with other transformations:**\n\n```sh\nopenmorph --input ./openapi \\\n  --mapping x-operation-group-name=x-fern-sdk-group-name \\\n  --vendor-providers fern \\\n  --pagination-priority cursor,offset,none \\\n  --flatten-responses \\\n  --config config.yaml\n```\n\n### Advanced Examples\n\n**Complex object defaults:**\n\n```yaml\ndefault_values:\n  enabled: true\n  rules:\n    settings_defaults:\n      target:\n        location: \"component\"\n      condition:\n        type: \"object\"\n        property_name: \"settings\"\n      template:\n        theme: \"light\"\n        notifications: true\n        language: \"en\"\n      priority: 4\n```\n\n**Array response defaults:**\n\n```yaml\ndefault_values:\n  enabled: true\n  rules:\n    array_defaults:\n      target:\n        location: \"response\"\n      condition:\n        type: \"array\"\n        http_methods: [\"get\"]\n        path_patterns: [\"/api/v1/.*\"]\n      value: []\n      priority: 5\n```\n\n### Rule Priority and Ordering\n\nRules are processed in priority order (highest priority first), allowing you to:\n\n1. Set broad defaults with low priority\n2. Override with specific defaults using higher priority\n3. Ensure consistent application order across runs\n\n```yaml\ndefault_values:\n  enabled: true\n  rules:\n    # Broad rule - low priority\n    all_strings:\n      condition:\n        type: \"string\"\n      value: \"default\"\n      priority: 1\n\n    # Specific rule - high priority (overrides above)\n    user_names:\n      condition:\n        type: \"string\"\n        property_name: \"name\"\n      value: \"Anonymous\"\n      priority: 10\n```\n\n### Best Practices\n\n1. **Use Regex Patterns**: Property name matching supports regex for flexible targeting\n2. **Prioritize Rules**: Use priority to control application order\n3. **Test with Dry-Run**: Always preview changes before applying\n4. **Backup Files**: Enable backup for safe operations\n5. **Combine Features**: Use alongside vendor extensions and other transformations\n6. **Document Rules**: Use clear rule names and comments in config files\n\n### Integration\n\nThe defaults feature integrates seamlessly with other OpenMorph features:\n\n- **Vendor Extensions**: Applied before vendor extensions\n- **Response Flattening**: Works on original schemas before flattening\n- **Validation**: Validates resulting OpenAPI specs\n- **Interactive Mode**: Preview all changes together\n- **Backup**: Automatic backup before modifications\n\n## Interactive TUI Controls\n\n- `j`/`k` or `left`/`right`: Navigate files\n- `a` or `enter`: Accept file changes\n- `s`: Skip file\n- `A`: Accept all\n- `S`: Skip all\n- `?`: Toggle help\n- `q` or `ctrl+c`: Quit\n\n## Output\n\n- **Dry Run:** Shows colorized before/after diffs for each key change, grouped by file.\n- **TUI:** Shows all key changes with navigation, full block diffs, and summary.\n- **CLI:** Prints a summary of accepted/skipped/transformed files.\n\n## Notes\n\n- Both YAML and JSON are supported.\n- All occurrences of a key are transformed, including in arrays/objects.\n- Backups are only created if `--backup` is specified.\n- Config file values are merged with CLI flags (CLI flags take precedence).\n\n## Security \u0026 Privacy\n\nOpenMorph is designed with security as a core principle:\n\n### Security Features\n\n- **No secrets storage** - No credentials or sensitive information are stored or required\n- **Input validation** - All user inputs are properly validated and sanitized\n- **Secure file handling** - Temporary files use secure creation and cleanup\n- **Vulnerability scanning** - Automated security scanning with govulncheck\n- **Dependency monitoring** - Regular dependency vulnerability checks\n- **Static code analysis** - CodeQL and additional security linters\n\n### Security Scanning\n\nWe use comprehensive security scanning:\n\n```bash\n# Run local security scan\nmake security\n\n# Run with detailed JSON output\nmake security-json\n```\n\n### Security Workflows\n\n- **Automated scanning** on every push and pull request\n- **Daily vulnerability checks** at 2 AM UTC\n- **Dependency review** for all pull requests\n- **SARIF integration** with GitHub Security tab\n\n### Reporting Security Issues\n\n**Please do not report security vulnerabilities through public GitHub issues.**\n\n- Create a private security advisory on GitHub\n- Use the \"Report a vulnerability\" feature in the Security tab\n- Include detailed reproduction steps and impact assessment\n\nFor more details, see our [Security Policy](SECURITY_POLICY.md) and [Security Guide](SECURITY.md).\n\n### Response Timeline\n\n- **Initial Response**: Within 24 hours\n- **Assessment**: Within 72 hours\n- **Critical fixes**: 24-48 hours\n- **High severity**: Within 1 week\n\n## Development\n\n### Release Management\n\nThis project uses automated release management with package managers support. See the [Auto-Release Guide](AUTO_RELEASE_GUIDE.md) for complete setup instructions.\n\nQuick commands:\n\n```bash\n# Validate setup\nmake validate\n\n# Create release\nmake version-release\n\n# Setup package managers\nmake setup-packages\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeveloperkunal%2Fopenmorph","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeveloperkunal%2Fopenmorph","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeveloperkunal%2Fopenmorph/lists"}