diff --git a/docs/public/docs/guide/cli/breaking-changes/breaking-changes.md b/docs/public/docs/guide/cli/breaking-changes/breaking-changes.md index c1221a43..db5be1ba 100644 --- a/docs/public/docs/guide/cli/breaking-changes/breaking-changes.md +++ b/docs/public/docs/guide/cli/breaking-changes/breaking-changes.md @@ -49,14 +49,19 @@ breaking: - "experimental" - "internal/proto" - "vendor" + + # Additional options to braking check + use: + - FILE ``` ### Configuration Options -| Option | Description | Default | Required | -|--------|-------------|---------|----------| -| `against_git_ref` | Git reference to compare against | `"master"` | No | -| `ignore` | List of directories to exclude from analysis | `[]` | No | +| Option | Description | Default | Required | +|-------------------|----------------------------------------------|---------|----------| +| `against_git_ref` | Git reference to compare against | `"master"` | No | +| `ignore` | List of directories to exclude from analysis | `[]` | No | +| `use` | List of braking check options | `[]` | No | ## Usage @@ -137,7 +142,7 @@ EasyP detects the following types of breaking changes: |----------------|-------------|---------------| | **WIRE** | Wire format compatibility only | ✅ **Full support** | | **WIRE+** | Wire + element deletion detection | ✅ **Current level** | -| **FILE** | Generated code compatibility | ❌ Partial (planned) | +| **FILE** | Generated code compatibility | ✅ **Current level** | ## Breaking Change Rules EasyP detects the following categories of breaking changes. Each rule has detailed documentation with examples: diff --git a/docs/public/search/index.en.json b/docs/public/search/index.en.json index 932f583a..06b951b8 100644 --- a/docs/public/search/index.en.json +++ b/docs/public/search/index.en.json @@ -1 +1 @@ -[{"id":"api-service/overview::top::0","title":"API Service Overview","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Centralized protobuf plugin execution service for consistent, isolated code generation**","content":"**Centralized protobuf plugin execution service for consistent, isolated code generation**"},{"id":"api-service/overview::top::1","title":"API Service Overview","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"The EasyP API Service eliminates plugin management chaos by providing centralized execution of protobuf/gRPC plugins as isolated Docker containers. It offers a unified platform for teams to standardize their code generat","content":"The EasyP API Service eliminates plugin management chaos by providing centralized execution of protobuf/gRPC plugins as isolated Docker containers. It offers a unified platform for teams to standardize their code generation workflows without the operational overhead of managing plugins across individual developer machines."},{"id":"api-service/overview::the-challenge::2","title":"API Service Overview","section":"The Challenge","path":"/docs/guide/api-service/overview#the-challenge","headings":["The Challenge"],"excerpt":"The Challenge Managing protobuf/gRPC code generation across development teams creates significant operational complexity:","content":"The Challenge Managing protobuf/gRPC code generation across development teams creates significant operational complexity:"},{"id":"api-service/overview::version-inconsistencies::3","title":"API Service Overview","section":"Version Inconsistencies","path":"/docs/guide/api-service/overview#version-inconsistencies","headings":["Version Inconsistencies"],"excerpt":"Version Inconsistencies Developers use different plugin versions locally, causing build failures and inconsistent generated code \"Works on my machine\" syndrome when generated code differs between environments Manual coor","content":"Version Inconsistencies Developers use different plugin versions locally, causing build failures and inconsistent generated code \"Works on my machine\" syndrome when generated code differs between environments Manual coordination required to keep entire teams synchronized on plugin versions"},{"id":"api-service/overview::operational-overhead::4","title":"API Service Overview","section":"Operational Overhead","path":"/docs/guide/api-service/overview#operational-overhead","headings":["Operational Overhead"],"excerpt":"Operational Overhead DevOps teams spend significant time managing plugin installations across developer machines Each new team member requires manual setup of correct plugin versions Plugin updates require coordinating w","content":"Operational Overhead DevOps teams spend significant time managing plugin installations across developer machines Each new team member requires manual setup of correct plugin versions Plugin updates require coordinating with every developer individually No centralized control over which plugin versions are approved for use"},{"id":"api-service/overview::security-compliance-risks::5","title":"API Service Overview","section":"Security & Compliance Risks","path":"/docs/guide/api-service/overview#security-compliance-risks","headings":["Security & Compliance Risks"],"excerpt":"Security & Compliance Risks Developers install plugins from various sources without security validation No audit trail of which plugins were used for which builds Difficult to enforce security policies on code generation","content":"Security & Compliance Risks Developers install plugins from various sources without security validation No audit trail of which plugins were used for which builds Difficult to enforce security policies on code generation tools"},{"id":"api-service/overview::the-solution-centralized-plugin-execution::6","title":"API Service Overview","section":"The Solution: Centralized Plugin Execution","path":"/docs/guide/api-service/overview#the-solution-centralized-plugin-execution","headings":["The Solution: Centralized Plugin Execution"],"excerpt":"The Solution: Centralized Plugin Execution EasyP API Service eliminates these operational headaches by centralizing plugin management:","content":"The Solution: Centralized Plugin Execution EasyP API Service eliminates these operational headaches by centralizing plugin management:"},{"id":"api-service/overview::the-solution-centralized-plugin-execution::7","title":"API Service Overview","section":"The Solution: Centralized Plugin Execution","path":"/docs/guide/api-service/overview#the-solution-centralized-plugin-execution","headings":["The Solution: Centralized Plugin Execution"],"excerpt":"The Solution: Centralized Plugin Execution Challenge Solution ----------- ---------- **Version Control** Deploy new plugin versions to entire team instantly via Docker images **Operations** Operations team controls plugi","content":"The Solution: Centralized Plugin Execution Challenge Solution ----------- ---------- **Version Control** Deploy new plugin versions to entire team instantly via Docker images **Operations** Operations team controls plugin configurations without touching developer machines **Security** All plugins run in isolated Docker containers with resource constraints **Consistency** Consistent execution environment regardless of developer's local setup **Developer Experience** No local plugin installation or maintenance required"},{"id":"api-service/overview::architecture-overview::8","title":"API Service Overview","section":"Architecture Overview","path":"/docs/guide/api-service/overview#architecture-overview","headings":["Architecture Overview"],"excerpt":"Architecture Overview The EasyP API Service uses a streamlined architecture focused on reliable plugin execution:","content":"Architecture Overview The EasyP API Service uses a streamlined architecture focused on reliable plugin execution:"},{"id":"api-service/overview::api-layer::9","title":"API Service Overview","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server**: Primary API for code generation requests Each plugin execution is a separate gRPC request Receives CodeGeneratorRequest from CLI","content":"API Layer **gRPC Server**: Primary API for code generation requests Each plugin execution is a separate gRPC request Receives CodeGeneratorRequest from CLI"},{"id":"api-service/overview::execution-engine::10","title":"API Service Overview","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime**: Isolated container execution for plugins Pulls plugin images from public Docker registries (Docker Hub, etc.) Enforces resource limits (CPU, memory) per plugin","content":"Execution Engine **Docker Runtime**: Isolated container execution for plugins Pulls plugin images from public Docker registries (Docker Hub, etc.) Enforces resource limits (CPU, memory) per plugin"},{"id":"api-service/overview::storage-layer::11","title":"API Service Overview","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL**: Stores plugin execution parameters - Resource limits (CPU, memory allocation) - Plugin configuration and metadata - Execution logs for auditing - _Note: Storage capabilities will be expanded","content":"Storage Layer **PostgreSQL**: Stores plugin execution parameters - Resource limits (CPU, memory allocation) - Plugin configuration and metadata - Execution logs for auditing - _Note: Storage capabilities will be expanded in future releases_"},{"id":"api-service/overview::monitoring::12","title":"API Service Overview","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus**: Metrics collection and monitoring Tracks execution times, success rates, and resource usage","content":"Monitoring **Prometheus**: Metrics collection and monitoring Tracks execution times, success rates, and resource usage"},{"id":"api-service/overview::local-execution-easyp-cli::13","title":"API Service Overview","section":"Local Execution (EasyP CLI)","path":"/docs/guide/api-service/overview#local-execution-easyp-cli","headings":["Local Execution (EasyP CLI)"],"excerpt":"Local Execution (EasyP CLI) When running locally, the EasyP CLI supports: **Installed plugins**: System-installed protoc plugins **WASM plugins**: Fast, lightweight WebAssembly plugins","content":"Local Execution (EasyP CLI) When running locally, the EasyP CLI supports: **Installed plugins**: System-installed protoc plugins **WASM plugins**: Fast, lightweight WebAssembly plugins"},{"id":"api-service/overview::remote-execution-api-service::14","title":"API Service Overview","section":"Remote Execution (API Service)","path":"/docs/guide/api-service/overview#remote-execution-api-service","headings":["Remote Execution (API Service)"],"excerpt":"Remote Execution (API Service) When using the API Service: **Docker only**: All plugins run as Docker containers **Centralized control**: Operations team manages available plugins **Consistent environment**: Same executi","content":"Remote Execution (API Service) When using the API Service: **Docker only**: All plugins run as Docker containers **Centralized control**: Operations team manages available plugins **Consistent environment**: Same execution environment for all developers"},{"id":"api-service/overview::execution-steps::15","title":"API Service Overview","section":"Execution Steps","path":"/docs/guide/api-service/overview#execution-steps","headings":["Execution Steps"],"excerpt":"Execution Steps **CLI Parsing**: CLI parses protobuf files locally **Request Sending**: CLI sends CodeGeneratorRequest to API Service (one request per plugin) **Parameter Lookup**: API Service fetches plugin execution pa","content":"Execution Steps **CLI Parsing**: CLI parses protobuf files locally **Request Sending**: CLI sends CodeGeneratorRequest to API Service (one request per plugin) **Parameter Lookup**: API Service fetches plugin execution parameters from PostgreSQL **Docker Execution**: API Service runs plugin in isolated Docker container **Metrics Recording**: Execution metrics are recorded (at end of request) **Response**: Generated code is returned to CLI"},{"id":"api-service/overview::key-features::16","title":"API Service Overview","section":"Key Features","path":"/docs/guide/api-service/overview#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- **🐳 Plugin Isolation** Each plugin runs in a secure, isolated Docker container **⚙️ Resource Control** CPU and memory limits enforced per plugin **📊 Metrics & Mo","content":"Key Features Feature Description --------- ------------- **🐳 Plugin Isolation** Each plugin runs in a secure, isolated Docker container **⚙️ Resource Control** CPU and memory limits enforced per plugin **📊 Metrics & Monitoring** Prometheus metrics for all operations **🔄 Version Management** Centralized plugin version control via Docker images **⚡ Simple Protocol** Standard CodeGeneratorRequest/Response protocol **🔒 Security First** Container isolation with resource constraints"},{"id":"api-service/overview::configuration::17","title":"API Service Overview","section":"Configuration","path":"/docs/guide/api-service/overview#configuration","headings":["Configuration"],"excerpt":"Configuration The service is configured via environment variables:","content":"Configuration The service is configured via environment variables:"},{"id":"api-service/overview::plugin-parameters-storage::18","title":"API Service Overview","section":"Plugin Parameters Storage","path":"/docs/guide/api-service/overview#plugin-parameters-storage","headings":["Plugin Parameters Storage"],"excerpt":"Plugin Parameters Storage PostgreSQL stores execution parameters for each plugin:","content":"Plugin Parameters Storage PostgreSQL stores execution parameters for each plugin:"},{"id":"api-service/overview::plugin-parameters-storage::19","title":"API Service Overview","section":"Plugin Parameters Storage","path":"/docs/guide/api-service/overview#plugin-parameters-storage","headings":["Plugin Parameters Storage"],"excerpt":"Plugin Parameters Storage ::: tip The storage schema and capabilities will be expanded in future releases to support additional features like audit logging, usage analytics, and plugin caching. :::","content":"Plugin Parameters Storage ::: tip The storage schema and capabilities will be expanded in future releases to support additional features like audit logging, usage analytics, and plugin caching. :::"},{"id":"api-service/overview::integration-with-easyp-cli::20","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI Configure your easyp.yaml to use remote plugin execution:","content":"Integration with EasyP CLI Configure your easyp.yaml to use remote plugin execution:"},{"id":"api-service/overview::integration-with-easyp-cli::21","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI Then generate code:","content":"Integration with EasyP CLI Then generate code:"},{"id":"api-service/overview::integration-with-easyp-cli::22","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI The CLI will: Parse your protobuf files Send separate requests to API Service for each plugin Receive generated code responses Write generated files to specified output directories","content":"Integration with EasyP CLI The CLI will: Parse your protobuf files Send separate requests to API Service for each plugin Receive generated code responses Write generated files to specified output directories"},{"id":"api-service/overview::available-metrics::23","title":"API Service Overview","section":"Available Metrics","path":"/docs/guide/api-service/overview#available-metrics","headings":["Available Metrics"],"excerpt":"Available Metrics Prometheus metrics exposed by the service:","content":"Available Metrics Prometheus metrics exposed by the service:"},{"id":"api-service/overview::available-metrics::24","title":"API Service Overview","section":"Available Metrics","path":"/docs/guide/api-service/overview#available-metrics","headings":["Available Metrics"],"excerpt":"Available Metrics Metric Description -------- ------------- easyp_api_service_api_grpc_server_handled_total Total gRPC requests by status code easyp_api_service_api_grpc_server_handling_seconds gRPC request latency histo","content":"Available Metrics Metric Description -------- ------------- easyp_api_service_api_grpc_server_handled_total Total gRPC requests by status code easyp_api_service_api_grpc_server_handling_seconds gRPC request latency histogram easyp_api_service_generated_plugin_code_total Plugin executions by plugin name easyp_api_service_repo_call_duration_seconds Database query latency easyp_api_service_repo_errors_total Database errors count easyp_api_service_standard_panics_total Recovered panics count"},{"id":"api-service/overview::performance-characteristics::25","title":"API Service Overview","section":"Performance Characteristics","path":"/docs/guide/api-service/overview#performance-characteristics","headings":["Performance Characteristics"],"excerpt":"Performance Characteristics Metric Typical Value Notes -------- --------------- ------- **Cold Start** 2-5 seconds First time pulling plugin image **Warm Start** 100-500ms Plugin image cached by Docker **Throughput** 20-","content":"Performance Characteristics Metric Typical Value Notes -------- --------------- ------- **Cold Start** 2-5 seconds First time pulling plugin image **Warm Start** 100-500ms Plugin image cached by Docker **Throughput** 20-50 concurrent Depends on available resources **Memory Usage** 50-200MB Per plugin execution"},{"id":"api-service/overview::container-isolation::26","title":"API Service Overview","section":"Container Isolation","path":"/docs/guide/api-service/overview#container-isolation","headings":["Container Isolation"],"excerpt":"Container Isolation Each plugin runs in a separate, ephemeral container No network access during plugin execution Resource limits (CPU, memory) enforced via Docker Containers destroyed after execution","content":"Container Isolation Each plugin runs in a separate, ephemeral container No network access during plugin execution Resource limits (CPU, memory) enforced via Docker Containers destroyed after execution"},{"id":"api-service/overview::api-security::27","title":"API Service Overview","section":"API Security","path":"/docs/guide/api-service/overview#api-security","headings":["API Security"],"excerpt":"API Security gRPC-based communication Support for authentication tokens (production deployments) Input validation for all requests Execution audit logs stored in PostgreSQL","content":"API Security gRPC-based communication Support for authentication tokens (production deployments) Input validation for all requests Execution audit logs stored in PostgreSQL"},{"id":"api-service/overview::scalability::28","title":"API Service Overview","section":"Scalability","path":"/docs/guide/api-service/overview#scalability","headings":["Scalability"],"excerpt":"Scalability **Horizontal scaling**: Deploy multiple service instances behind load balancer **Resource management**: Configure appropriate CPU/memory limits per plugin **Database**: PostgreSQL can be replicated for high a","content":"Scalability **Horizontal scaling**: Deploy multiple service instances behind load balancer **Resource management**: Configure appropriate CPU/memory limits per plugin **Database**: PostgreSQL can be replicated for high availability"},{"id":"api-service/overview::monitoring::29","title":"API Service Overview","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus metrics**: Monitor all aspects of service health **Alerting**: Set up alerts for high error rates or slow execution **Logs**: Structured logging for debugging and audit trails","content":"Monitoring **Prometheus metrics**: Monitor all aspects of service health **Alerting**: Set up alerts for high error rates or slow execution **Logs**: Structured logging for debugging and audit trails"},{"id":"api-service/overview::future-enhancements::30","title":"API Service Overview","section":"Future Enhancements","path":"/docs/guide/api-service/overview#future-enhancements","headings":["Future Enhancements"],"excerpt":"Future Enhancements The API Service is actively developed with planned features including: Plugin result caching for faster repeated executions Enhanced audit logging and usage analytics Support for custom plugin registr","content":"Future Enhancements The API Service is actively developed with planned features including: Plugin result caching for faster repeated executions Enhanced audit logging and usage analytics Support for custom plugin registries Advanced resource scheduling and optimization"},{"id":"api-service/overview::community-and-support::31","title":"API Service Overview","section":"Community and Support","path":"/docs/guide/api-service/overview#community-and-support","headings":["Community and Support"],"excerpt":"Community and Support **💬 Telegram Chat** - Community discussion **🐛 GitHub Issues** - Bug reports and features **📖 Documentation** - Complete documentation","content":"Community and Support **💬 Telegram Chat** - Community discussion **🐛 GitHub Issues** - Bug reports and features **📖 Documentation** - Complete documentation"},{"id":"api-service/overview::community-and-support::32","title":"API Service Overview","section":"Community and Support","path":"/docs/guide/api-service/overview#community-and-support","headings":["Community and Support"],"excerpt":"Community and Support *Simplify your protobuf workflows with centralized plugin execution*","content":"Community and Support *Simplify your protobuf workflows with centralized plugin execution*"},{"id":"ci-cd/github-actions::top::0","title":"Github Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Github Actions Work in progress","content":"Github Actions Work in progress"},{"id":"ci-cd/gitlab::top::0","title":"Gitlab","path":"/docs/guide/ci-cd/gitlab","headings":[],"excerpt":"Gitlab Work in progress","content":"Gitlab Work in progress"},{"id":"cli/auto-completion/auto-completion::zsh-auto-completion::0","title":"Auto completion","section":"zsh auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#zsh-auto-completion","headings":["zsh auto-completion"],"excerpt":"zsh auto-completion Add the following line to your ~/.zshrc startup script:","content":"zsh auto-completion Add the following line to your ~/.zshrc startup script:"},{"id":"cli/auto-completion/auto-completion::zsh-auto-completion::1","title":"Auto completion","section":"zsh auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#zsh-auto-completion","headings":["zsh auto-completion"],"excerpt":"zsh auto-completion Re-launch your shell or run:","content":"zsh auto-completion Re-launch your shell or run:"},{"id":"cli/auto-completion/auto-completion::bash-auto-completion::2","title":"Auto completion","section":"Bash auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#bash-auto-completion","headings":["Bash auto-completion"],"excerpt":"Bash auto-completion Install bash-completion and add the software to your ~/.bashrc. Add the following line to your ~/.bashrc startup script:","content":"Bash auto-completion Install bash-completion and add the software to your ~/.bashrc. Add the following line to your ~/.bashrc startup script:"},{"id":"cli/auto-completion/auto-completion::bash-auto-completion::3","title":"Auto completion","section":"Bash auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#bash-auto-completion","headings":["Bash auto-completion"],"excerpt":"Bash auto-completion Re-launch your shell or run:","content":"Bash auto-completion Re-launch your shell or run:"},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Breaking Changes Detection","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"EasyP's breaking changes detection helps you maintain backward compatibility in your protobuf APIs by automatically identifying changes that could break existing clients. This is crucial for maintaining stable APIs in pr","content":"EasyP's breaking changes detection helps you maintain backward compatibility in your protobuf APIs by automatically identifying changes that could break existing clients. This is crucial for maintaining stable APIs in production environments."},{"id":"cli/breaking-changes/breaking-changes::overview::1","title":"Breaking Changes Detection","section":"Overview","path":"/docs/guide/cli/breaking-changes/breaking-changes#overview","headings":["Overview"],"excerpt":"Overview The breaking changes checker compares your current protobuf files against a previous version (typically from another Git branch) and identifies modifications that could cause compatibility issues for existing cl","content":"Overview The breaking changes checker compares your current protobuf files against a previous version (typically from another Git branch) and identifies modifications that could cause compatibility issues for existing clients."},{"id":"cli/breaking-changes/breaking-changes::key-features::2","title":"Breaking Changes Detection","section":"Key Features","path":"/docs/guide/cli/breaking-changes/breaking-changes#key-features","headings":["Key Features"],"excerpt":"Key Features **Git-based Comparison**: Compare against any Git reference (branch, tag, or commit) **Comprehensive Analysis**: Checks services, messages, enums, fields, and imports **Selective Ignore**: Skip specific dire","content":"Key Features **Git-based Comparison**: Compare against any Git reference (branch, tag, or commit) **Comprehensive Analysis**: Checks services, messages, enums, fields, and imports **Selective Ignore**: Skip specific directories from breaking change analysis **Detailed Reports**: Clear error messages with file locations and line numbers"},{"id":"cli/breaking-changes/breaking-changes::how-it-works::3","title":"Breaking Changes Detection","section":"How It Works","path":"/docs/guide/cli/breaking-changes/breaking-changes#how-it-works","headings":["How It Works"],"excerpt":"How It Works The breaking changes detector follows this process:","content":"How It Works The breaking changes detector follows this process:"},{"id":"cli/breaking-changes/breaking-changes::how-it-works::4","title":"Breaking Changes Detection","section":"How It Works","path":"/docs/guide/cli/breaking-changes/breaking-changes#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Checkout Comparison Branch**: Retrieves proto files from the specified Git reference **Parse Both Versions**: Analyzes current and previous proto file structures **Compare Entities**: Systematically checks","content":"How It Works **Checkout Comparison Branch**: Retrieves proto files from the specified Git reference **Parse Both Versions**: Analyzes current and previous proto file structures **Compare Entities**: Systematically checks all protobuf elements for breaking changes **Generate Report**: Produces detailed issue reports with locations and descriptions"},{"id":"cli/breaking-changes/breaking-changes::detection-level::5","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level EasyP implements **WIRE+ level** breaking change detection: ✅ **Full wire format compatibility** - ensures old and new versions can exchange data ✅ **Element deletion detection** - catches deleted service","content":"Detection Level EasyP implements **WIRE+ level** breaking change detection: ✅ **Full wire format compatibility** - ensures old and new versions can exchange data ✅ **Element deletion detection** - catches deleted services, messages, fields, etc. ✅ **Type safety** - detects incompatible type changes ❌ **Field/method renames** - currently not detected (planned for future releases) ❌ **File-level changes** - package moves, file options not checked yet"},{"id":"cli/breaking-changes/breaking-changes::detection-level::6","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level This provides strong compatibility guarantees while being less strict than some tools that check generated code compatibility.","content":"Detection Level This provides strong compatibility guarantees while being less strict than some tools that check generated code compatibility."},{"id":"cli/breaking-changes/breaking-changes::configuration::7","title":"Breaking Changes Detection","section":"Configuration","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration","headings":["Configuration"],"excerpt":"Configuration Configure breaking changes detection in your easyp.yaml:","content":"Configuration Configure breaking changes detection in your easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::configuration-options::8","title":"Breaking Changes Detection","section":"Configuration Options","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration-options","headings":["Configuration Options"],"excerpt":"Configuration Options Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git reference to compare against \"master\" No ignore List of directories to exclude from analysis [] No","content":"Configuration Options Option Description Default Required -------- ------------- --------- ---------- against_git_ref Git reference to compare against \"master\" No ignore List of directories to exclude from analysis [] No"},{"id":"cli/breaking-changes/breaking-changes::basic-usage::9","title":"Breaking Changes Detection","section":"Basic Usage","path":"/docs/guide/cli/breaking-changes/breaking-changes#basic-usage","headings":["Basic Usage"],"excerpt":"Basic Usage Compare current changes against the main branch:","content":"Basic Usage Compare current changes against the main branch:"},{"id":"cli/breaking-changes/breaking-changes::using-configuration-file::10","title":"Breaking Changes Detection","section":"Using Configuration File","path":"/docs/guide/cli/breaking-changes/breaking-changes#using-configuration-file","headings":["Using Configuration File"],"excerpt":"Using Configuration File With a custom configuration file:","content":"Using Configuration File With a custom configuration file:"},{"id":"cli/breaking-changes/breaking-changes::override-git-reference::11","title":"Breaking Changes Detection","section":"Override Git Reference","path":"/docs/guide/cli/breaking-changes/breaking-changes#override-git-reference","headings":["Override Git Reference"],"excerpt":"Override Git Reference Override the configured branch:","content":"Override Git Reference Override the configured branch:"},{"id":"cli/breaking-changes/breaking-changes::detection-level::12","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level EasyP currently implements **WIRE+ level** breaking change detection, which provides comprehensive wire format compatibility plus some generated code protections:","content":"Detection Level EasyP currently implements **WIRE+ level** breaking change detection, which provides comprehensive wire format compatibility plus some generated code protections:"},{"id":"cli/breaking-changes/breaking-changes::comparison-with-buf-categories::13","title":"Breaking Changes Detection","section":"Comparison with Buf Categories","path":"/docs/guide/cli/breaking-changes/breaking-changes#comparison-with-buf-categories","headings":["Comparison with Buf Categories"],"excerpt":"Comparison with Buf Categories Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletio","content":"Comparison with Buf Categories Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌ ❌ ✅ ✅ Message deletion ❌ ❌ ✅ ✅ Field deletion (by number) ✅ ✅ ✅ ✅ Enum deletion ❌ ❌ ✅ ✅ Enum value deletion ✅ ✅ ✅ ✅ OneOf deletion ❌ ❌ ✅ ✅ Import deletion ❌ ❌ ✅ ✅ **Type Changes** Field type change ✅ ✅ ✅ ✅ RPC request/response type ✅ ✅ ✅ ✅ Optional/required changes ✅ ✅ ✅ ✅ **Naming (Generated Code)** Field rename (same number) ❌ ✅ ✅ ❌ Enum value rename ❌ ✅ ✅ ✅ **File Structure** Package change ✅ ✅ ✅ ❌ File options (go_package, etc) ❌ ❌ ✅ ❌ Moving types between files ❌ ❌ ✅ ❌"},{"id":"cli/breaking-changes/breaking-changes::what-this-means::14","title":"Breaking Changes Detection","section":"What This Means","path":"/docs/guide/cli/breaking-changes/breaking-changes#what-this-means","headings":["What This Means"],"excerpt":"What This Means **✅ EasyP WILL detect:** All wire format breaking changes Deletion of services, methods, messages, fields Type changes that break serialization Enum value renames (same number, different name)","content":"What This Means **✅ EasyP WILL detect:** All wire format breaking changes Deletion of services, methods, messages, fields Type changes that break serialization Enum value renames (same number, different name)"},{"id":"cli/breaking-changes/breaking-changes::what-this-means::15","title":"Breaking Changes Detection","section":"What This Means","path":"/docs/guide/cli/breaking-changes/breaking-changes#what-this-means","headings":["What This Means"],"excerpt":"What This Means **❌ EasyP will NOT detect:** Field renames (same number, different name) Package name changes File option changes (go_package, java_package, etc.) Moving types between files in the same package","content":"What This Means **❌ EasyP will NOT detect:** Field renames (same number, different name) Package name changes File option changes (go_package, java_package, etc.) Moving types between files in the same package"},{"id":"cli/breaking-changes/breaking-changes::breaking-change-rules::16","title":"Breaking Changes Detection","section":"Breaking Change Rules","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-change-rules","headings":["Breaking Change Rules"],"excerpt":"Breaking Change Rules EasyP detects the following types of breaking changes:","content":"Breaking Change Rules EasyP detects the following types of breaking changes:"},{"id":"cli/breaking-changes/breaking-changes::comparison-with-other-tools::17","title":"Breaking Changes Detection","section":"Comparison with Other Tools","path":"/docs/guide/cli/breaking-changes/breaking-changes#comparison-with-other-tools","headings":["Comparison with Other Tools"],"excerpt":"Comparison with Other Tools Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Wire format compatibility only ✅ **Full support** **WIRE+** Wire + element deletion detection ","content":"Comparison with Other Tools Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Wire format compatibility only ✅ **Full support** **WIRE+** Wire + element deletion detection ✅ **Current level** **FILE** Generated code compatibility ❌ Partial (planned)"},{"id":"cli/breaking-changes/breaking-changes::breaking-change-rules::18","title":"Breaking Changes Detection","section":"Breaking Change Rules","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-change-rules","headings":["Breaking Change Rules"],"excerpt":"Breaking Change Rules EasyP detects the following categories of breaking changes. Each rule has detailed documentation with examples:","content":"Breaking Change Rules EasyP detects the following categories of breaking changes. Each rule has detailed documentation with examples:"},{"id":"cli/breaking-changes/breaking-changes::service-and-rpc-changes::19","title":"Breaking Changes Detection","section":"🚨 Service and RPC Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-and-rpc-changes","headings":["🚨 Service and RPC Changes"],"excerpt":"🚨 Service and RPC Changes Rule Description Status ------ ------------- --------- SERVICE_NO_DELETE Services cannot be deleted ✅ Implemented RPC_NO_DELETE RPC methods cannot be deleted ✅ Implemented RPC_SAME_REQUEST_TYPE","content":"🚨 Service and RPC Changes Rule Description Status ------ ------------- --------- SERVICE_NO_DELETE Services cannot be deleted ✅ Implemented RPC_NO_DELETE RPC methods cannot be deleted ✅ Implemented RPC_SAME_REQUEST_TYPE RPC request types cannot be changed ✅ Implemented RPC_SAME_RESPONSE_TYPE RPC response types cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::message-and-field-changes::20","title":"Breaking Changes Detection","section":"📦 Message and Field Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-and-field-changes","headings":["📦 Message and Field Changes"],"excerpt":"📦 Message and Field Changes Rule Description Status ------ ------------- --------- MESSAGE_NO_DELETE Messages cannot be deleted ✅ Implemented FIELD_NO_DELETE Fields cannot be deleted ✅ Implemented FIELD_SAME_TYPE Field ","content":"📦 Message and Field Changes Rule Description Status ------ ------------- --------- MESSAGE_NO_DELETE Messages cannot be deleted ✅ Implemented FIELD_NO_DELETE Fields cannot be deleted ✅ Implemented FIELD_SAME_TYPE Field types cannot be changed ✅ Implemented FIELD_SAME_CARDINALITY Field optionality (optional/required) cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::enum-changes::21","title":"Breaking Changes Detection","section":"🔢 Enum Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum-changes","headings":["🔢 Enum Changes"],"excerpt":"🔢 Enum Changes Rule Description Status ------ ------------- --------- ENUM_NO_DELETE Enums cannot be deleted ✅ Implemented ENUM_VALUE_NO_DELETE Enum values cannot be deleted ✅ Implemented ENUM_VALUE_SAME_NAME Enum value","content":"🔢 Enum Changes Rule Description Status ------ ------------- --------- ENUM_NO_DELETE Enums cannot be deleted ✅ Implemented ENUM_VALUE_NO_DELETE Enum values cannot be deleted ✅ Implemented ENUM_VALUE_SAME_NAME Enum value names cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::oneof-changes::22","title":"Breaking Changes Detection","section":"🔗 OneOf Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof-changes","headings":["🔗 OneOf Changes"],"excerpt":"🔗 OneOf Changes Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIELD_","content":"🔗 OneOf Changes Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIELD_SAME_TYPE OneOf field types cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::import-changes::23","title":"Breaking Changes Detection","section":"📥 Import Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#import-changes","headings":["📥 Import Changes"],"excerpt":"📥 Import Changes Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Import Changes Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::not-currently-detected::24","title":"Breaking Changes Detection","section":"Not Currently Detected","path":"/docs/guide/cli/breaking-changes/breaking-changes#not-currently-detected","headings":["Not Currently Detected"],"excerpt":"Not Currently Detected The following changes are **NOT detected** by EasyP (but may break generated code):","content":"Not Currently Detected The following changes are **NOT detected** by EasyP (but may break generated code):"},{"id":"cli/breaking-changes/breaking-changes::not-currently-detected::25","title":"Breaking Changes Detection","section":"Not Currently Detected","path":"/docs/guide/cli/breaking-changes/breaking-changes#not-currently-detected","headings":["Not Currently Detected"],"excerpt":"Not Currently Detected Change Type Example Impact ------------- --------- --------- Field renaming string name = 1 → string full_name = 1 Generated code breaks Package changes package v1 → package v2 Import paths change ","content":"Not Currently Detected Change Type Example Impact ------------- --------- --------- Field renaming string name = 1 → string full_name = 1 Generated code breaks Package changes package v1 → package v2 Import paths change File options option go_package = \"old\" → option go_package = \"new\" Generated code location Moving between files Message moved to different .proto file Import dependencies"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::26","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation For comprehensive examples and migration strategies, see the individual rule documentation:","content":"Detailed Rules Documentation For comprehensive examples and migration strategies, see the individual rule documentation:"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::27","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation **Service Changes**: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE **Message Changes**: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDI","content":"Detailed Rules Documentation **Service Changes**: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE **Message Changes**: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY **Enum Changes**: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME **OneOf Changes**: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE **Import Changes**: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::28","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation Each rule includes: ❌ **Bad examples** with actual breaking changes ✅ **Good alternatives** showing safe approaches 🔧 **Migration strategies** for handling necessary changes 📋 **Real error ","content":"Detailed Rules Documentation Each rule includes: ❌ **Bad examples** with actual breaking changes ✅ **Good alternatives** showing safe approaches 🔧 **Migration strategies** for handling necessary changes 📋 **Real error messages** from EasyP"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::29","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) ```proto // Adding new elements is always safe message User { string name = 1; string email = 2; string phone = 3; // ✅ New field - safe }","content":"✅ Safe Changes (Always Allowed) ```proto // Adding new elements is always safe message User { string name = 1; string email = 2; string phone = 3; // ✅ New field - safe }"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::30","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ New RPC - safe }","content":"✅ Safe Changes (Always Allowed) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ New RPC - safe }"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::31","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ New enum value - safe } ```","content":"✅ Safe Changes (Always Allowed) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ New enum value - safe } ```"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes-always-detected::32","title":"Breaking Changes Detection","section":"❌ Breaking Changes (Always Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes-always-detected","headings":["❌ Breaking Changes (Always Detected)"],"excerpt":"❌ Breaking Changes (Always Detected) ```proto // Deletions and type changes break compatibility message User { string name = 1; // ❌ Deleted field - BREAKING }","content":"❌ Breaking Changes (Always Detected) ```proto // Deletions and type changes break compatibility message User { string name = 1; // ❌ Deleted field - BREAKING }"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes-always-detected::33","title":"Breaking Changes Detection","section":"❌ Breaking Changes (Always Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes-always-detected","headings":["❌ Breaking Changes (Always Detected)"],"excerpt":"❌ Breaking Changes (Always Detected) service UserService { // ❌ Deleted RPC method - BREAKING rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Changed request type - BREAKING } ```","content":"❌ Breaking Changes (Always Detected) service UserService { // ❌ Deleted RPC method - BREAKING rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Changed request type - BREAKING } ```"},{"id":"cli/breaking-changes/breaking-changes::scenario-3-breaking-changes-currently-not-detected::34","title":"Breaking Changes Detection","section":"Scenario 3: Breaking Changes (Currently Not Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#scenario-3-breaking-changes-currently-not-detected","headings":["Scenario 3: Breaking Changes (Currently Not Detected)"],"excerpt":"Scenario 3: Breaking Changes (Currently Not Detected) ```proto // 🟡 Breaks generated code but passes EasyP checks message User { string user_name = 1; // Renamed from \"name\" string user_email = 2; // Renamed from \"email","content":"Scenario 3: Breaking Changes (Currently Not Detected) ```proto // 🟡 Breaks generated code but passes EasyP checks message User { string user_name = 1; // Renamed from \"name\" string user_email = 2; // Renamed from \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::scenario-3-breaking-changes-currently-not-detected::35","title":"Breaking Changes Detection","section":"Scenario 3: Breaking Changes (Currently Not Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#scenario-3-breaking-changes-currently-not-detected","headings":["Scenario 3: Breaking Changes (Currently Not Detected)"],"excerpt":"Scenario 3: Breaking Changes (Currently Not Detected) service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Renamed from GetUser } ```","content":"Scenario 3: Breaking Changes (Currently Not Detected) service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Renamed from GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::1-regular-checks::36","title":"Breaking Changes Detection","section":"1. Regular Checks","path":"/docs/guide/cli/breaking-changes/breaking-changes#1-regular-checks","headings":["1. Regular Checks"],"excerpt":"Regular Checks Run breaking change detection in your CI/CD pipeline:","content":"Regular Checks Run breaking change detection in your CI/CD pipeline:"},{"id":"cli/breaking-changes/breaking-changes::2-branch-protection::37","title":"Breaking Changes Detection","section":"2. Branch Protection","path":"/docs/guide/cli/breaking-changes/breaking-changes#2-branch-protection","headings":["2. Branch Protection"],"excerpt":"Branch Protection Use breaking change checks to protect important branches:","content":"Branch Protection Use breaking change checks to protect important branches:"},{"id":"cli/breaking-changes/breaking-changes::3-versioning-strategy::38","title":"Breaking Changes Detection","section":"3. Versioning Strategy","path":"/docs/guide/cli/breaking-changes/breaking-changes#3-versioning-strategy","headings":["3. Versioning Strategy"],"excerpt":"Versioning Strategy When breaking changes are necessary:","content":"Versioning Strategy When breaking changes are necessary:"},{"id":"cli/breaking-changes/breaking-changes::3-versioning-strategy::39","title":"Breaking Changes Detection","section":"3. Versioning Strategy","path":"/docs/guide/cli/breaking-changes/breaking-changes#3-versioning-strategy","headings":["3. Versioning Strategy"],"excerpt":"Versioning Strategy Create a new package version (e.g., myservice.v2) Maintain the old version during migration period Use deprecation notices in the old version","content":"Versioning Strategy Create a new package version (e.g., myservice.v2) Maintain the old version during migration period Use deprecation notices in the old version"},{"id":"cli/breaking-changes/breaking-changes::4-ignore-patterns::40","title":"Breaking Changes Detection","section":"4. Ignore Patterns","path":"/docs/guide/cli/breaking-changes/breaking-changes#4-ignore-patterns","headings":["4. Ignore Patterns"],"excerpt":"Ignore Patterns Use ignore patterns wisely:","content":"Ignore Patterns Use ignore patterns wisely:"},{"id":"cli/breaking-changes/breaking-changes::issue-repository-does-not-exist::41","title":"Breaking Changes Detection","section":"Issue: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-repository-does-not-exist","headings":["Issue: \"Repository does not exist\""],"excerpt":"Issue: \"Repository does not exist\" **Solution**: Ensure you're running the command in a Git repository with the specified branch available.","content":"Issue: \"Repository does not exist\" **Solution**: Ensure you're running the command in a Git repository with the specified branch available."},{"id":"cli/breaking-changes/breaking-changes::issue-cannot-find-git-ref::42","title":"Breaking Changes Detection","section":"Issue: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-cannot-find-git-ref","headings":["Issue: \"Cannot find git ref\""],"excerpt":"Issue: \"Cannot find git ref\" **Solution**: Verify the branch/tag name exists and is accessible:","content":"Issue: \"Cannot find git ref\" **Solution**: Verify the branch/tag name exists and is accessible:"},{"id":"cli/breaking-changes/breaking-changes::issue-false-positives-in-generated-code::43","title":"Breaking Changes Detection","section":"Issue: False Positives in Generated Code","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-false-positives-in-generated-code","headings":["Issue: False Positives in Generated Code"],"excerpt":"Issue: False Positives in Generated Code **Solution**: Add generated directories to ignore list:","content":"Issue: False Positives in Generated Code **Solution**: Add generated directories to ignore list:"},{"id":"cli/breaking-changes/breaking-changes::issue-large-number-of-changes::44","title":"Breaking Changes Detection","section":"Issue: Large Number of Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-large-number-of-changes","headings":["Issue: Large Number of Changes"],"excerpt":"Issue: Large Number of Changes **Solution**: For major refactoring, consider: Creating a new API version Implementing changes incrementally Using feature flags for gradual rollout","content":"Issue: Large Number of Changes **Solution**: For major refactoring, consider: Creating a new API version Implementing changes incrementally Using feature flags for gradual rollout"},{"id":"cli/breaking-changes/breaking-changes::github-actions::45","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions ```yaml name: API Compatibility Check","content":"GitHub Actions ```yaml name: API Compatibility Check"},{"id":"cli/breaking-changes/breaking-changes::github-actions::46","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions on: pull_request: branches: [ main ]","content":"GitHub Actions on: pull_request: branches: [ main ]"},{"id":"cli/breaking-changes/breaking-changes::github-actions::47","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Fetch full history - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tec","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Fetch full history - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.sh sh - name: Check for breaking changes run: ./bin/easyp breaking --against origin/main ```"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::48","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit Hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::49","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit Hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::50","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook if [ $current_branch = $protected_branch ]; then echo \"Running breaking changes check...\" easyp breaking --against HEAD~1 if [ $? -eq 1 ]; then echo \"❌ Breaking changes detected. Push rejected.\" exit 1 fi","content":"Pre-commit Hook if [ $current_branch = $protected_branch ]; then echo \"Running breaking changes check...\" easyp breaking --against HEAD~1 if [ $? -eq 1 ]; then echo \"❌ Breaking changes detected. Push rejected.\" exit 1 fi echo \"✅ No breaking changes detected.\" fi ```"},{"id":"cli/breaking-changes/breaking-changes::debug-mode::51","title":"Breaking Changes Detection","section":"Debug Mode","path":"/docs/guide/cli/breaking-changes/breaking-changes#debug-mode","headings":["Debug Mode"],"excerpt":"Debug Mode Enable debug logging for detailed information:","content":"Debug Mode Enable debug logging for detailed information:"},{"id":"cli/breaking-changes/breaking-changes::manual-comparison::52","title":"Breaking Changes Detection","section":"Manual Comparison","path":"/docs/guide/cli/breaking-changes/breaking-changes#manual-comparison","headings":["Manual Comparison"],"excerpt":"Manual Comparison For complex cases, you can manually inspect the comparison:","content":"Manual Comparison For complex cases, you can manually inspect the comparison:"},{"id":"cli/breaking-changes/breaking-changes::performance-optimization::53","title":"Breaking Changes Detection","section":"Performance Optimization","path":"/docs/guide/cli/breaking-changes/breaking-changes#performance-optimization","headings":["Performance Optimization"],"excerpt":"Performance Optimization For large repositories:","content":"Performance Optimization For large repositories:"},{"id":"cli/breaking-changes/breaking-changes::performance-optimization::54","title":"Breaking Changes Detection","section":"Performance Optimization","path":"/docs/guide/cli/breaking-changes/breaking-changes#performance-optimization","headings":["Performance Optimization"],"excerpt":"Performance Optimization The breaking changes detection in EasyP provides a robust foundation for maintaining API compatibility while allowing your protobuf schemas to evolve safely over time.","content":"Performance Optimization The breaking changes detection in EasyP provides a robust foundation for maintaining API compatibility while allowing your protobuf schemas to evolve safely over time."},{"id":"cli/breaking-changes/rules/enum-no-delete::top::0","title":"ENUM_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":[],"excerpt":"This rule checks that no enums are deleted from proto files. Deleting an enum breaks both wire format compatibility and generated code, as existing data may contain values from the deleted enum and client code depends on","content":"This rule checks that no enums are deleted from proto files. Deleting an enum breaks both wire format compatibility and generated code, as existing data may contain values from the deleted enum and client code depends on the generated enum types."},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::1","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::2","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::3","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Bad enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::4","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::5","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::6","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::7","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad // UserRole enum was deleted - BREAKING CHANGE!","content":"Bad // UserRole enum was deleted - BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::8","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole no longer exists! } ```","content":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole no longer exists! } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::9","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested enum deletion:**","content":"More Examples **Nested enum deletion:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::10","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --] STATUS_INACTIVE = 2; // [!code --] } ","content":"More Examples ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --] STATUS_INACTIVE = 2; // [!code --] } // [!code --] }"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::11","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status enum deleted // Status nested enum was deleted } ```","content":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status enum deleted // Status nested enum was deleted } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::12","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the enum:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::13","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::14","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Good enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::15","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::16","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new enum:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::17","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::18","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserRole { option deprecated = true; // [!code focus] // Old enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Good enum UserRole { option deprecated = true; // [!code focus] // Old enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::19","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserPermission { // [!code focus] // New enum with better design USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PER","content":"Good enum UserPermission { // [!code focus] // New enum with better design USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERMISSION_ADMIN = 3; // [!code focus] } // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::20","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] // Old field UserPermission created_by_permission = 4; // [!code focus] // New field } ```","content":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] // Old field UserPermission created_by_permission = 4; // [!code focus] // New field } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::impact::21","title":"ENUM_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with the deleted enum cannot be deserialized **Generated Code:** Enum types/constants are removed, breaking client compilation **Field References:** Fields using the deleted enum typ","content":"Impact **Wire Format:** Existing data with the deleted enum cannot be deserialized **Generated Code:** Enum types/constants are removed, breaking client compilation **Field References:** Fields using the deleted enum type become invalid **Switch Statements:** Client code with enum switch cases breaks"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::22","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR ","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR after deletion }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::23","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check role switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR: undefined type // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR: undefined type // User logic }","content":"Real-World Example // Check role switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR: undefined type // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR: undefined type // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::24","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::25","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_PENDING\", \"created_by_role\": \"USER_ROLE_ADMIN\" }","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_PENDING\", \"created_by_role\": \"USER_ROLE_ADMIN\" }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::26","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After UserRole deletion - deserialization fails // Parser doesn't know how to handle \"created_by_role\" field ```","content":"Real-World Example // After UserRole deletion - deserialization fails // Parser doesn't know how to handle \"created_by_role\" field ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::27","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:**","content":"Real-World Example **Server implementation breaks:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::28","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the enum first:**","content":"Migration Strategy **Deprecate the enum first:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::29","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using in new fields** and deprecate existing fields:","content":"Migration Strategy **Stop using in new fields** and deprecate existing fields:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::30","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create replacement** if needed:","content":"Migration Strategy **Create replacement** if needed:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::31","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both during transition:","content":"Migration Strategy **Update server code** to handle both during transition:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::32","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum-redesign::33","title":"ENUM_NO_DELETE","section":"Enum Redesign","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum-redesign","headings":["Enum Redesign"],"excerpt":"Enum Redesign ```proto // Instead of deleting old enum enum Priority { option deprecated = true; // Deprecate old design PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Enum Redesign ```proto // Instead of deleting old enum enum Priority { option deprecated = true; // Deprecate old design PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum-redesign::34","title":"ENUM_NO_DELETE","section":"Enum Redesign","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum-redesign","headings":["Enum Redesign"],"excerpt":"Enum Redesign enum TaskPriority { // Create new enum with better naming TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Enum Redesign enum TaskPriority { // Create new enum with better naming TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::35","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums ```proto // Instead of deleting multiple enums enum Status { option deprecated = true; // Keep old enum STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Consolidating Enums ```proto // Instead of deleting multiple enums enum Status { option deprecated = true; // Keep old enum STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::36","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums enum State { option deprecated = true; // Keep old enum STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Consolidating Enums enum State { option deprecated = true; // Keep old enum STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::37","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums enum EntityStatus { // New consolidated enum ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Consolidating Enums enum EntityStatus { // New consolidated enum ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::38","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package ```proto // Instead of deleting from current package enum UserRole { option deprecated = true; // Mark as deprecated USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Moving Enum to Different Package ```proto // Instead of deleting from current package enum UserRole { option deprecated = true; // Mark as deprecated USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::39","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package // Import from new location import \"common/roles.proto\";","content":"Moving Enum to Different Package // Import from new location import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::40","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; // Reference from new package } ```","content":"Moving Enum to Different Package message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; // Reference from new package } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::41","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration ```proto // Clean approach - new package version package myapi.v2;","content":"Version Migration ```proto // Clean approach - new package version package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::42","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration // Redesigned enums without deprecated ones enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Version Migration // Redesigned enums without deprecated ones enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::43","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration message Order { string id = 1; UserPermission created_by_permission = 2; // Clean design in v2 } ```","content":"Version Migration message Order { string id = 1; UserPermission created_by_permission = 2; // Clean design in v2 } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::0","title":"ENUM_VALUE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":[],"excerpt":"This rule checks that no enum values are deleted from enums. Deleting an enum value breaks both wire format compatibility and generated code, as existing data may contain the deleted enum value and client code may refere","content":"This rule checks that no enum values are deleted from enums. Deleting an enum value breaks both wire format compatibility and generated code, as existing data may contain the deleted enum value and client code may reference the generated constants."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::1","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::2","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::3","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::4","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::5","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; // ORDER_STATUS_CANCELLED = 5; // [!code --] Deleted enum v","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; // ORDER_STATUS_CANCELLED = 5; // [!code --] Deleted enum value - BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::6","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Deleted enum value - BREAKING! } ```","content":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Deleted enum value - BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::7","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Multiple value deletions:**","content":"More Examples **Multiple value deletions:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::8","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_GUEST = 1; USER_ROLE_USER = 2; USER_ROLE_MODERATOR = 3; USER_ROLE_ADMIN = 4; USER_ROLE_SUPERADMIN = 5; }","content":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_GUEST = 1; USER_ROLE_USER = 2; USER_ROLE_MODERATOR = 3; USER_ROLE_ADMIN = 4; USER_ROLE_SUPERADMIN = 5; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::9","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_USER = 2; USER_ROLE_ADMIN = 4; // USER_ROLE_GUEST = 1; // BREAKING: deleted // USER_ROLE_MODERATOR = 3; // BREAKING: deleted","content":"More Examples // After - BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_USER = 2; USER_ROLE_ADMIN = 4; // USER_ROLE_GUEST = 1; // BREAKING: deleted // USER_ROLE_MODERATOR = 3; // BREAKING: deleted // USER_ROLE_SUPERADMIN = 5; // BREAKING: deleted } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::10","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the enum values:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the enum values:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::11","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5 [deprecated = true]; // [!code ","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::12","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Good enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::13","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good **Or reserve the enum values after removal:** ```proto syntax = \"proto3\";","content":"Good **Or reserve the enum values after removal:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::14","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus] ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER","content":"Good enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus] ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::15","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus] PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Good enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus] PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::impact::16","title":"ENUM_VALUE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with deleted enum values cannot be properly deserialized **Generated Code:** Enum constants are removed, breaking client compilation **Client Applications:** Code referencing deleted","content":"Impact **Wire Format:** Existing data with deleted enum values cannot be properly deserialized **Generated Code:** Enum constants are removed, breaking client compilation **Client Applications:** Code referencing deleted enum values fails to compile **Switch Statements:** Case statements for deleted values cause compilation errors **Default Handling:** Unknown enum values may be handled differently"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::17","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR after deletion }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR after deletion }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::18","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch statement breaks switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Handle pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined constant // Handle can","content":"Real-World Example // Switch statement breaks switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Handle pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined constant // Handle cancellation default: // Handle unknown }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::19","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::20","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes problematic:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_CANCELLED\" }","content":"Real-World Example **Existing data becomes problematic:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_CANCELLED\" }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::21","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After enum value deletion // Data deserializes but status becomes UNSPECIFIED (0) // or causes parsing errors depending on implementation ```","content":"Real-World Example // After enum value deletion // Data deserializes but status becomes UNSPECIFIED (0) // or causes parsing errors depending on implementation ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::22","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - server handles all enum values func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_OR","content":"Real-World Example **Server validation breaks:** ```go // Before - server handles all enum values func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHIPPED, OrderStatus_ORDER_STATUS_DELIVERED, OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::23","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Server logic that depends on cancelled status func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR: undefined } ```","content":"Real-World Example // Server logic that depends on cancelled status func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR: undefined } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::24","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate enum values first:**","content":"Migration Strategy **Deprecate enum values first:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::25","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using deprecated values** in new code:","content":"Migration Strategy **Stop using deprecated values** in new code:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::26","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update client code** to handle deprecated values gracefully:","content":"Migration Strategy **Update client code** to handle deprecated values gracefully:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::27","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve the values** after sufficient migration period:","content":"Migration Strategy **Reserve the values** after sufficient migration period:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::28","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Never reuse enum numbers** - they must remain reserved permanently","content":"Migration Strategy **Never reuse enum numbers** - they must remain reserved permanently"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::proto2-vs-proto3-behavior::29","title":"ENUM_VALUE_NO_DELETE","section":"Proto2 vs Proto3 Behavior","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#proto2-vs-proto3-behavior","headings":["Proto2 vs Proto3 Behavior"],"excerpt":"Proto2 vs Proto3 Behavior ```proto // Proto2: Unknown enum values are preserved in unknown fields // Proto3: Unknown enum values are preserved as-is // Both cases: Don't delete values that might exist in stored data","content":"Proto2 vs Proto3 Behavior ```proto // Proto2: Unknown enum values are preserved in unknown fields // Proto3: Unknown enum values are preserved as-is // Both cases: Don't delete values that might exist in stored data"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::proto2-vs-proto3-behavior::30","title":"ENUM_VALUE_NO_DELETE","section":"Proto2 vs Proto3 Behavior","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#proto2-vs-proto3-behavior","headings":["Proto2 vs Proto3 Behavior"],"excerpt":"Proto2 vs Proto3 Behavior // Safe approach for both syntax versions: enum MyEnum { MY_ENUM_UNSPECIFIED = 0; MY_ENUM_VALUE_OLD = 1 [deprecated = true]; // Don't delete MY_ENUM_VALUE_NEW = 2; } ```","content":"Proto2 vs Proto3 Behavior // Safe approach for both syntax versions: enum MyEnum { MY_ENUM_UNSPECIFIED = 0; MY_ENUM_VALUE_OLD = 1 [deprecated = true]; // Don't delete MY_ENUM_VALUE_NEW = 2; } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::0","title":"ENUM_VALUE_SAME_NAME","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":[],"excerpt":"This rule checks that enum values maintain the same name for each number. Changing an enum value's name (while keeping the same number) breaks both JSON compatibility and generated code, as clients expect specific consta","content":"This rule checks that enum values maintain the same name for each number. Changing an enum value's name (while keeping the same number) breaks both JSON compatibility and generated code, as clients expect specific constant names."},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::1","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::2","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::3","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::4","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Changed from ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code ","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Changed from ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Changed from ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::5","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples **Multiple renames breaking clients:**","content":"More Examples **Multiple renames breaking clients:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::6","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::7","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"More Examples // After - ALL BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER = 3; // BREAKING: USER -> MEMBER } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::8","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good **Instead of renaming, add new values and deprecate old ones:** ```proto syntax = \"proto3\";","content":"Good **Instead of renaming, add new values and deprecate old ones:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::9","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2 [deprecated = true]; // [!code focus] ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4 [deprecated = true]; /","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2 [deprecated = true]; // [!code focus] ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4 [deprecated = true]; // [!code focus] ORDER_STATUS_APPROVED = 5; // [!code focus] // New value instead of renaming ORDER_STATUS_COMPLETED = 6; // [!code focus] // New value instead of renaming } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::10","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good **Or create a new enum version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new enum version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::11","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::12","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // Clean names in v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ``","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // Clean names in v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::impact::13","title":"ENUM_VALUE_SAME_NAME","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Constant names change, breaking client compilation **JSON Compatibility:** JSON serialization uses enum names, breaking parsers **Client Applications:** Code referencing old constant names fail","content":"Impact **Generated Code:** Constant names change, breaking client compilation **JSON Compatibility:** JSON serialization uses enum names, breaking parsers **Client Applications:** Code referencing old constant names fails to compile **Documentation:** API docs become outdated with wrong enum names"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::14","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::15","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After rename - compilation fails status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined constant if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined con","content":"Real-World Example // After rename - compilation fails status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined constant if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined constant // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::16","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **JSON compatibility breaks:** ```json // Before - JSON uses old names { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Real-World Example **JSON compatibility breaks:** ```json // Before - JSON uses old names { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::17","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - parser expects new names { \"status\": \"ORDER_STATUS_APPROVED\" // Old JSON fails to parse } ```","content":"Real-World Example // After - parser expects new names { \"status\": \"ORDER_STATUS_APPROVED\" // Old JSON fails to parse } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::18","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new enum values** instead of renaming:","content":"Migration Strategy **Add new enum values** instead of renaming:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::19","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new values during transition","content":"Migration Strategy **Update server code** to handle both old and new values during transition"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::20","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new enum values","content":"Migration Strategy **Migrate clients** to use new enum values"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::21","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove deprecated values** in next major version:","content":"Migration Strategy **Remove deprecated values** in next major version:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias-exception::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias Exception","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias-exception","headings":["Allow Alias Exception"],"excerpt":"Allow Alias Exception With allow_alias = true, you can temporarily have multiple names for the same value:","content":"Allow Alias Exception With allow_alias = true, you can temporarily have multiple names for the same value:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias-exception::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias Exception","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias-exception","headings":["Allow Alias Exception"],"excerpt":"Allow Alias Exception Note: EasyP currently detects this as breaking even with allow_alias. This may be refined in future versions.","content":"Allow Alias Exception Note: EasyP currently detects this as breaking even with allow_alias. This may be refined in future versions."},{"id":"cli/breaking-changes/rules/field-no-delete::top::0","title":"FIELD_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":[],"excerpt":"This rule checks that no message fields are deleted. Deleting a field breaks both wire format compatibility and generated code, as existing data may contain the deleted field and client code may reference it.","content":"This rule checks that no message fields are deleted. Deleting a field breaks both wire format compatibility and generated code, as existing data may contain the deleted field and client code may reference it."},{"id":"cli/breaking-changes/rules/field-no-delete::bad::1","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::2","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::3","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::4","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; // phone field was deleted - BREAKING CHANGE! } ```","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; // phone field was deleted - BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::good::5","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the field:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::good::6","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Good message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::good::7","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good **Or reserve the field number after removal:** ```proto syntax = \"proto3\";","content":"Good **Or reserve the field number after removal:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::good::8","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Good message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::impact::9","title":"FIELD_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Old messages with the deleted field cannot be properly deserialized **Generated Code:** Field accessors are removed, breaking client compilation **Data Loss:** Existing serialized data loses infor","content":"Impact **Wire Format:** Old messages with the deleted field cannot be properly deserialized **Generated Code:** Field accessors are removed, breaking client compilation **Data Loss:** Existing serialized data loses information **JSON Compatibility:** JSON parsers expect the field to exist"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::10","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::11","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop writing to the field** in your application code","content":"Migration Strategy **Stop writing to the field** in your application code"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::12","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve the field** in next version to prevent accidental reuse:","content":"Migration Strategy **Reserve the field** in next version to prevent accidental reuse:"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::13","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Never reuse field numbers** - they must remain reserved permanently","content":"Migration Strategy **Never reuse field numbers** - they must remain reserved permanently"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::0","title":"FIELD_SAME_CARDINALITY","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":[],"excerpt":"This rule checks that message fields maintain the same cardinality (optionality). Changing a field's cardinality breaks both wire format compatibility and generated code, as the presence semantics and client code expecta","content":"This rule checks that message fields maintain the same cardinality (optionality). Changing a field's cardinality breaks both wire format compatibility and generated code, as the presence semantics and client code expectations differ between optional and required fields."},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::1","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::2","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; }","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::3","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Bad message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::4","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::5","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; optional string email = 2; // [!code --] Changed from required to optional int32 age = 3; }","content":"Bad message User { string name = 1; optional string email = 2; // [!code --] Changed from required to optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::6","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message CreateUserRequest { string name = 1; string email = 2; // [!code --] Changed from optional to required string phone = 3; } ```","content":"Bad message CreateUserRequest { string name = 1; string email = 2; // [!code --] Changed from optional to required string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::7","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples **Proto2 to Proto3 migration issues:**","content":"More Examples **Proto2 to Proto3 migration issues:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::8","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before (proto2) syntax = \"proto2\";","content":"More Examples ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::9","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"More Examples message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::10","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"More Examples // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::11","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK: repeated unchanged } ```","content":"More Examples message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK: repeated unchanged } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::12","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good **Instead of changing cardinality, add new field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing cardinality, add new field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::13","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality int32 age = 3; optional string email_optional = 4; // [!code focus] // New field with desired cardi","content":"Good message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality int32 age = 3; optional string email_optional = 4; // [!code focus] // New field with desired cardinality }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::14","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality string phone = 3; string email_required = 4; // [!code focus] // New field wi","content":"Good message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality string phone = 3; string email_required = 4; // [!code focus] // New field with desired cardinality } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::15","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good **Or create a new message version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::16","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::17","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message User { string name = 1; optional string email = 2; // [!code focus] // Clean cardinality in v2 int32 age = 3; }","content":"Good message User { string name = 1; optional string email = 2; // [!code focus] // Clean cardinality in v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::18","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message CreateUserRequest { string name = 1; string email = 2; // [!code focus] // Required in v2 string phone = 3; } ```","content":"Good message CreateUserRequest { string name = 1; string email = 2; // [!code focus] // Required in v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::impact::19","title":"FIELD_SAME_CARDINALITY","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Field presence semantics change, breaking deserialization expectations **Generated Code:** Field accessor methods change (hasField(), clearField()) **Validation:** Required field validation change","content":"Impact **Wire Format:** Field presence semantics change, breaking deserialization expectations **Generated Code:** Field accessor methods change (hasField(), clearField()) **Validation:** Required field validation changes at runtime **Default Values:** Optional vs required fields handle defaults differently"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::20","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks with cardinality changes:** ```go // Before - required field (proto3 implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", // Must be set Age: 30, }","content":"Real-World Example **Client code breaks with cardinality changes:** ```go // Before - required field (proto3 implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", // Must be set Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::21","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check if email is set (implicit presence) if user.Email != \"\" { // Email is provided }","content":"Real-World Example // Check if email is set (implicit presence) if user.Email != \"\" { // Email is provided }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::22","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - optional field (explicit presence) user := &myapi.User{ Name: \"John\", Age: 30, // Email can be nil/unset }","content":"Real-World Example // After - optional field (explicit presence) user := &myapi.User{ Name: \"John\", Age: 30, // Email can be nil/unset }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::23","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check if email is set (explicit presence) if user.Email != nil && *user.Email != \"\" { // Different API! // Email is provided }","content":"Real-World Example // Check if email is set (explicit presence) if user.Email != nil && *user.Email != \"\" { // Different API! // Email is provided }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::24","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Setting email also changes user.Email = &emailValue // Pointer assignment vs direct ```","content":"Real-World Example // Setting email also changes user.Email = &emailValue // Pointer assignment vs direct ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::25","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - implicit required field func validateUser(user *User) error { if user.Email == \"\" { // Empty string check return errors.New(\"email is required\") } return","content":"Real-World Example **Server validation breaks:** ```go // Before - implicit required field func validateUser(user *User) error { if user.Email == \"\" { // Empty string check return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::26","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - explicit optional field func validateUser(user *User) error { if user.Email == nil { // Nil pointer check return errors.New(\"email is required\") } if *user.Email == \"\" { // Dereference to ch","content":"Real-World Example // After - explicit optional field func validateUser(user *User) error { if user.Email == nil { // Nil pointer check return errors.New(\"email is required\") } if *user.Email == \"\" { // Dereference to check empty return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::27","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new field** with correct cardinality:","content":"Migration Strategy **Add new field** with correct cardinality:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::28","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Dual-write period** - populate both fields during transition:","content":"Migration Strategy **Dual-write period** - populate both fields during transition:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::29","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update clients** to use new field gradually:","content":"Migration Strategy **Update clients** to use new field gradually:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::30","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old field** in next major version:","content":"Migration Strategy **Remove old field** in next major version:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-to-proto3-migration::31","title":"FIELD_SAME_CARDINALITY","section":"Proto2 to Proto3 Migration","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-to-proto3-migration","headings":["Proto2 to Proto3 Migration"],"excerpt":"Proto2 to Proto3 Migration ```proto // Instead of direct syntax migration syntax = \"proto3\"; message Order { string id = 1; // BREAKING: was required in proto2 }","content":"Proto2 to Proto3 Migration ```proto // Instead of direct syntax migration syntax = \"proto3\"; message Order { string id = 1; // BREAKING: was required in proto2 }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-to-proto3-migration::32","title":"FIELD_SAME_CARDINALITY","section":"Proto2 to Proto3 Migration","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-to-proto3-migration","headings":["Proto2 to Proto3 Migration"],"excerpt":"Proto2 to Proto3 Migration // Maintain semantics during migration syntax = \"proto3\"; message Order { string id = 1; // Keep as implicit required // Add explicit optional fields only when needed optional string notes = 2;","content":"Proto2 to Proto3 Migration // Maintain semantics during migration syntax = \"proto3\"; message Order { string id = 1; // Keep as implicit required // Add explicit optional fields only when needed optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-optional-fields-required::33","title":"FIELD_SAME_CARDINALITY","section":"Making Optional Fields Required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-optional-fields-required","headings":["Making Optional Fields Required"],"excerpt":"Making Optional Fields Required ```proto // Instead of changing existing field message CreateUserRequest { string name = 1; string email = 2; // BREAKING: was optional }","content":"Making Optional Fields Required ```proto // Instead of changing existing field message CreateUserRequest { string name = 1; string email = 2; // BREAKING: was optional }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-optional-fields-required::34","title":"FIELD_SAME_CARDINALITY","section":"Making Optional Fields Required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-optional-fields-required","headings":["Making Optional Fields Required"],"excerpt":"Making Optional Fields Required // Add new required field message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; // New required field } ```","content":"Making Optional Fields Required // Add new required field message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; // New required field } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-required-fields-optional::35","title":"FIELD_SAME_CARDINALITY","section":"Making Required Fields Optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-required-fields-optional","headings":["Making Required Fields Optional"],"excerpt":"Making Required Fields Optional ```proto // Instead of changing existing field message User { optional string phone = 3; // BREAKING: was required }","content":"Making Required Fields Optional ```proto // Instead of changing existing field message User { optional string phone = 3; // BREAKING: was required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-required-fields-optional::36","title":"FIELD_SAME_CARDINALITY","section":"Making Required Fields Optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-required-fields-optional","headings":["Making Required Fields Optional"],"excerpt":"Making Required Fields Optional // Add new optional field message User { string phone = 3 [deprecated = true]; // Keep required optional string phone_optional = 4; // New optional field } ```","content":"Making Required Fields Optional // Add new optional field message User { string phone = 3 [deprecated = true]; // Keep required optional string phone_optional = 4; // New optional field } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3-cardinality::37","title":"FIELD_SAME_CARDINALITY","section":"Proto3 Cardinality","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3-cardinality","headings":["Proto3 Cardinality"],"excerpt":"Proto3 Cardinality **Implicit optional**: string name = 1; (default in proto3) **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 Cardinality **Implicit optional**: string name = 1; (default in proto3) **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-cardinality::38","title":"FIELD_SAME_CARDINALITY","section":"Proto2 Cardinality","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-cardinality","headings":["Proto2 Cardinality"],"excerpt":"Proto2 Cardinality **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 Cardinality **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking-changes-matrix::39","title":"FIELD_SAME_CARDINALITY","section":"Breaking Changes Matrix","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking-changes-matrix","headings":["Breaking Changes Matrix"],"excerpt":"Breaking Changes Matrix From To Result ------ ---- --------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Single ","content":"Breaking Changes Matrix From To Result ------ ---- --------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Single ❌ BREAKING Field Map ❌ BREAKING Map Field ❌ BREAKING"},{"id":"cli/breaking-changes/rules/field-same-type::top::0","title":"FIELD_SAME_TYPE","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":[],"excerpt":"This rule checks that message fields maintain the same type. Changing a field's type breaks wire format compatibility and generated code, as the binary representation and client code expectations differ between types.","content":"This rule checks that message fields maintain the same type. Changing a field's type breaks wire format compatibility and generated code, as the binary representation and client code expectations differ between types."},{"id":"cli/breaking-changes/rules/field-same-type::bad::1","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::bad::2","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Bad message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::bad::3","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::bad::4","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string bool available = 3; } ```","content":"Bad message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::5","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Incompatible type changes:**","content":"More Examples **Incompatible type changes:**"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::6","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"More Examples ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::7","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"More Examples // After - ALL BREAKING CHANGES! message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status = 4; // enum -> int32: BREAKING } ```"},{"id":"cli/breaking-changes/rules/field-same-type::good::8","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good **Instead of changing type, add a new field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing type, add a new field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::good::9","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] bool available = 3; string price_formatted = 4; // [!code focus] // New field for string price } ```","content":"Good message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] bool available = 3; string price_formatted = 4; // [!code focus] // New field for string price } ```"},{"id":"cli/breaking-changes/rules/field-same-type::good::10","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good **Or create a new message version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::good::11","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/field-same-type::good::12","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good message Product { string name = 1; string price = 2; // [!code focus] // Now string in v2 bool available = 3; } ```","content":"Good message Product { string name = 1; string price = 2; // [!code focus] // Now string in v2 bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::impact::13","title":"FIELD_SAME_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** Field types change, breaking client compilation **Runtime Errors:** Type mismatches cause parsing failures **Data ","content":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** Field types change, breaking client compilation **Runtime Errors:** Type mismatches cause parsing failures **Data Corruption:** Incorrect interpretation of binary data"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::14","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new field** with correct type:","content":"Migration Strategy **Add new field** with correct type:"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::15","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Dual-write period** - populate both fields during transition","content":"Migration Strategy **Dual-write period** - populate both fields during transition"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::16","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update clients** to use new field","content":"Migration Strategy **Update clients** to use new field"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::17","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old field** in next major version:","content":"Migration Strategy **Remove old field** in next major version:"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::18","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) Note: EasyP currently treats ALL type changes as breaking. However, some changes are technically wire-compatible:","content":"Safe Type Changes (Wire Compatible) Note: EasyP currently treats ALL type changes as breaking. However, some changes are technically wire-compatible:"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::19","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) int32 ↔ uint32 (same encoding) int64 ↔ uint64 (same encoding) string → bytes (if UTF-8 valid)","content":"Safe Type Changes (Wire Compatible) int32 ↔ uint32 (same encoding) int64 ↔ uint64 (same encoding) string → bytes (if UTF-8 valid)"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::20","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) These may be supported in future EasyP versions with different strictness levels.","content":"Safe Type Changes (Wire Compatible) These may be supported in future EasyP versions with different strictness levels."},{"id":"cli/breaking-changes/rules/import-no-delete::top::0","title":"IMPORT_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":[],"excerpt":"This rule checks that no import statements are deleted from proto files. Deleting an import breaks both wire format compatibility and generated code, as the imported types may be referenced in the current file and removi","content":"This rule checks that no import statements are deleted from proto files. Deleting an import breaks both wire format compatibility and generated code, as the imported types may be referenced in the current file and removing the import makes those types unavailable."},{"id":"cli/breaking-changes/rules/import-no-delete::bad::1","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::2","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Bad import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::3","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; common.User customer = 4; common.Address shipping_address = 5; } ```","content":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; common.User customer = 4; common.Address shipping_address = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::4","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::5","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/user.proto\"; // [!code --] Deleted import - BREAKING! // import \"common","content":"Bad import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/user.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/address.proto\"; // [!code --] Deleted import - BREAKING!"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::6","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration not available common.User customer = 4; // ERROR: User not available common.Ad","content":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration not available common.User customer = 4; // ERROR: User not available common.Address shipping_address = 5; // ERROR: Address not available } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::7","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Service definition breaks with deleted imports:**","content":"More Examples **Service definition breaks with deleted imports:**"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::8","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"More Examples ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::9","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); }","content":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); }"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::10","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING: deleted","content":"More Examples // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING: deleted"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::11","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations not available get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) return","content":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations not available get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: types not available } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::good::12","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, keep unused imports:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, keep unused imports:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::good::13","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep even if unused import \"common/user.proto\"; // [!code focus] // Keep even if unused import \"common/address.p","content":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep even if unused import \"common/user.proto\"; // [!code focus] // Keep even if unused import \"common/address.proto\"; // [!code focus] // Keep even if unused"},{"id":"cli/breaking-changes/rules/import-no-delete::good::14","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Removed fields that used Duration, User, Address but kept imports } ```","content":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Removed fields that used Duration, User, Address but kept imports } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::good::15","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with equivalent types while keeping imports:** ```proto syntax = \"proto3\";","content":"Good **Or replace with equivalent types while keeping imports:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::good::16","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep original import import \"common/user.proto\"; // [!code focus] // Keep original import import \"common/address","content":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep original import import \"common/user.proto\"; // [!code focus] // Keep original import import \"common/address.proto\"; // [!code focus] // Keep original import import \"common/v2/user.proto\"; // [!code focus] // Add new import"},{"id":"cli/breaking-changes/rules/import-no-delete::good::17","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] // Keep old field common.User customer = 4 [deprecated = tr","content":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] // Keep old field common.User customer = 4 [deprecated = true]; // [!code focus] // Keep old field common.Address shipping_address = 5 [deprecated = true]; // [!code focus] // Keep old field int32 processing_seconds = 6; // [!code focus] // New field instead of Duration common.v2.UserProfile customer_v2 = 7; // [!code focus] // New field with updated type string shipping_address_text = 8; // [!code focus] // New field with simpler type } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::impact::18","title":"IMPORT_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Imported types become unavailable, breaking compilation **Wire Format:** Messages using imported types cannot be deserialized **Field References:** Any field using imported types becomes invali","content":"Impact **Generated Code:** Imported types become unavailable, breaking compilation **Wire Format:** Messages using imported types cannot be deserialized **Field References:** Any field using imported types becomes invalid **Service Definitions:** RPC methods using imported types break **Options Usage:** Custom options from imports become unavailable"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::19","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", CreatedAt: timestamppb.New(time.Now()), // Uses google.protobuf.Timestamp Customer: &common.User{ // ERR","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", CreatedAt: timestamppb.New(time.Now()), // Uses google.protobuf.Timestamp Customer: &common.User{ // ERROR after import deletion Id: \"user456\", Name: \"John Doe\", }, ShippingAddress: &common.Address{ // ERROR after import deletion Street: \"123 Main St\", City: \"New York\", }, }"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::20","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: common.User // undefined: common.Address ```","content":"Real-World Example // Generated code compilation fails: // undefined: common.User // undefined: common.Address ```"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::21","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:**","content":"Real-World Example **Server implementation breaks:**"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::22","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Proto compilation breaks:**","content":"Real-World Example **Proto compilation breaks:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::23","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Keep imports even when unused:**","content":"Migration Strategy **Keep imports even when unused:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::24","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new imports alongside old ones:**","content":"Migration Strategy **Add new imports alongside old ones:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::25","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate fields using old imports gradually:**","content":"Migration Strategy **Deprecate fields using old imports gradually:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::26","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::27","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Only remove imports in major version updates** after all fields are migrated","content":"Migration Strategy **Only remove imports in major version updates** after all fields are migrated"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::28","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies ```proto // Instead of deleting old import immediately // import \"old/user.proto\"; // Don't delete!","content":"Replacing Dependencies ```proto // Instead of deleting old import immediately // import \"old/user.proto\"; // Don't delete!"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::29","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies // Keep both during transition import \"old/user.proto\"; // Keep for backward compatibility import \"new/user.proto\"; // Add new dependency","content":"Replacing Dependencies // Keep both during transition import \"old/user.proto\"; // Keep for backward compatibility import \"new/user.proto\"; // Add new dependency"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::30","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Replacing Dependencies message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::removing-unused-features::31","title":"IMPORT_NO_DELETE","section":"Removing Unused Features","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#removing-unused-features","headings":["Removing Unused Features"],"excerpt":"Removing Unused Features ```proto // Even if removing features, keep imports import \"feature/analytics.proto\"; // Keep even if analytics removed","content":"Removing Unused Features ```proto // Even if removing features, keep imports import \"feature/analytics.proto\"; // Keep even if analytics removed"},{"id":"cli/breaking-changes/rules/import-no-delete::removing-unused-features::32","title":"IMPORT_NO_DELETE","section":"Removing Unused Features","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#removing-unused-features","headings":["Removing Unused Features"],"excerpt":"Removing Unused Features message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Field removed but import kept } ```","content":"Removing Unused Features message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Field removed but import kept } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf-version-migration::33","title":"IMPORT_NO_DELETE","section":"Protobuf Version Migration","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf-version-migration","headings":["Protobuf Version Migration"],"excerpt":"Protobuf Version Migration ```proto // When migrating protobuf versions, keep old imports import \"google/protobuf/timestamp.proto\"; // Keep standard imports import \"google/protobuf/duration.proto\"; // Even if switching t","content":"Protobuf Version Migration ```proto // When migrating protobuf versions, keep old imports import \"google/protobuf/timestamp.proto\"; // Keep standard imports import \"google/protobuf/duration.proto\"; // Even if switching to alternatives"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf-version-migration::34","title":"IMPORT_NO_DELETE","section":"Protobuf Version Migration","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf-version-migration","headings":["Protobuf Version Migration"],"excerpt":"Protobuf Version Migration // Prefer keeping both old and new approaches message Event { google.protobuf.Timestamp timestamp = 1; // Keep old int64 timestamp_millis = 2; // Add alternative } ```","content":"Protobuf Version Migration // Prefer keeping both old and new approaches message Event { google.protobuf.Timestamp timestamp = 1; // Keep old int64 timestamp_millis = 2; // Add alternative } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::35","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies ```proto // Instead of removing complex type imports // import \"complex/config.proto\"; // Don't delete!","content":"Simplifying Dependencies ```proto // Instead of removing complex type imports // import \"complex/config.proto\"; // Don't delete!"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::36","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies // Keep complex import, add simple alternative import \"complex/config.proto\";","content":"Simplifying Dependencies // Keep complex import, add simple alternative import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::37","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies message Settings { complex.ConfigData config = 1 [deprecated = true]; // Keep complex option string config_json = 2; // Add simple option } ```","content":"Simplifying Dependencies message Settings { complex.ConfigData config = 1 [deprecated = true]; // Keep complex option string config_json = 2; // Add simple option } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-deletion-vs-field-usage::38","title":"IMPORT_NO_DELETE","section":"Import Deletion vs Field Usage","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-deletion-vs-field-usage","headings":["Import Deletion vs Field Usage"],"excerpt":"Import Deletion vs Field Usage ```proto // Import deletion breaks even if types aren't directly used as fields import \"common/enums.proto\";","content":"Import Deletion vs Field Usage ```proto // Import deletion breaks even if types aren't directly used as fields import \"common/enums.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::import-deletion-vs-field-usage::39","title":"IMPORT_NO_DELETE","section":"Import Deletion vs Field Usage","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-deletion-vs-field-usage","headings":["Import Deletion vs Field Usage"],"excerpt":"Import Deletion vs Field Usage message Order { // Even if no fields directly use common.enums types, // nested messages or oneof fields might use them oneof payment { CreditCardPayment card = 1; // This might internally ","content":"Import Deletion vs Field Usage message Order { // Even if no fields directly use common.enums types, // nested messages or oneof fields might use them oneof payment { CreditCardPayment card = 1; // This might internally use common.enums } } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::transitive-dependencies::40","title":"IMPORT_NO_DELETE","section":"Transitive Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#transitive-dependencies","headings":["Transitive Dependencies"],"excerpt":"Transitive Dependencies ```proto // Deleting an import can break transitive dependencies import \"user.proto\"; // Don't delete even if not directly used","content":"Transitive Dependencies ```proto // Deleting an import can break transitive dependencies import \"user.proto\"; // Don't delete even if not directly used"},{"id":"cli/breaking-changes/rules/import-no-delete::transitive-dependencies::41","title":"IMPORT_NO_DELETE","section":"Transitive Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#transitive-dependencies","headings":["Transitive Dependencies"],"excerpt":"Transitive Dependencies message Order { PaymentInfo payment = 1; // PaymentInfo might internally reference user.proto types } ```","content":"Transitive Dependencies message Order { PaymentInfo payment = 1; // PaymentInfo might internally reference user.proto types } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::json-serialization-impact::42","title":"IMPORT_NO_DELETE","section":"JSON Serialization Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#json-serialization-impact","headings":["JSON Serialization Impact"],"excerpt":"JSON Serialization Impact ```proto // Imports affect JSON field names and validation import \"google/protobuf/field_mask.proto\";","content":"JSON Serialization Impact ```proto // Imports affect JSON field names and validation import \"google/protobuf/field_mask.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::json-serialization-impact::43","title":"IMPORT_NO_DELETE","section":"JSON Serialization Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#json-serialization-impact","headings":["JSON Serialization Impact"],"excerpt":"JSON Serialization Impact message UpdateRequest { google.protobuf.FieldMask update_mask = 1; // JSON serialization depends on import } ```","content":"JSON Serialization Impact message UpdateRequest { google.protobuf.FieldMask update_mask = 1; // JSON serialization depends on import } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-auditing::44","title":"IMPORT_NO_DELETE","section":"Import Auditing","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-auditing","headings":["Import Auditing"],"excerpt":"Import Auditing ```bash Check which imports are actually used $ grep -r \"google.protobuf.Duration\" *.proto $ grep -r \"common.User\" *.proto","content":"Import Auditing ```bash Check which imports are actually used $ grep -r \"google.protobuf.Duration\" *.proto $ grep -r \"common.User\" *.proto"},{"id":"cli/breaking-changes/rules/import-no-delete::import-auditing::45","title":"IMPORT_NO_DELETE","section":"Import Auditing","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-auditing","headings":["Import Auditing"],"excerpt":"Import Auditing But still keep imports even if grep shows no usage! ```","content":"Import Auditing But still keep imports even if grep shows no usage! ```"},{"id":"cli/breaking-changes/rules/import-no-delete::different-breaking-change-types::46","title":"IMPORT_NO_DELETE","section":"Different Breaking Change Types","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#different-breaking-change-types","headings":["Different Breaking Change Types"],"excerpt":"Different Breaking Change Types ```proto // Import deletion (this rule) // import \"user.proto\"; // BREAKING: import deleted","content":"Different Breaking Change Types ```proto // Import deletion (this rule) // import \"user.proto\"; // BREAKING: import deleted"},{"id":"cli/breaking-changes/rules/import-no-delete::different-breaking-change-types::47","title":"IMPORT_NO_DELETE","section":"Different Breaking Change Types","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#different-breaking-change-types","headings":["Different Breaking Change Types"],"excerpt":"Different Breaking Change Types // vs Field deletion (different rule) message Order { string id = 1; // User customer = 2; // BREAKING: field deleted (different from import) } ```","content":"Different Breaking Change Types // vs Field deletion (different rule) message Order { string id = 1; // User customer = 2; // BREAKING: field deleted (different from import) } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::0","title":"MESSAGE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":[],"excerpt":"This rule checks that no messages are deleted from proto files. Deleting a message breaks both wire format compatibility and generated code, as existing data may reference the deleted message and client code depends on t","content":"This rule checks that no messages are deleted from proto files. Deleting a message breaks both wire format compatibility and generated code, as existing data may reference the deleted message and client code depends on the generated types."},{"id":"cli/breaking-changes/rules/message-no-delete::bad::1","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::2","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; Address address = 3; }","content":"Bad message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::3","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Bad message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::4","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; User user = 2; } ```","content":"Bad message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::5","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::6","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address message no longer exists! }","content":"Bad message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address message no longer exists! }"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::7","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad // Address message was deleted - BREAKING CHANGE!","content":"Bad // Address message was deleted - BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::8","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; User user = 2; } ```","content":"Bad message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::9","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested message deletion:**","content":"More Examples **Nested message deletion:**"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::10","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"More Examples ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::11","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile message deleted // Profile nested message was deleted } ```","content":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile message deleted // Profile nested message was deleted } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::good::12","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the message:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the message:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::good::13","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::14","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::15","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; User user = 2; } ```","content":"Good message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::good::16","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new message version:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::good::17","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Old field AddressV2 address_v2 = 4; // [!code focus] // New field with better structure }","content":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Old field AddressV2 address_v2 = 4; // [!code focus] // New field with better structure }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::18","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::19","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message AddressV2 { // [!code focus] string street_address = 1; // [!code focus] string city = 2; // [!code focus] string state = 3; // [!code focus] string postal_code = 4; // [!code focus] string country = 5; // [","content":"Good message AddressV2 { // [!code focus] string street_address = 1; // [!code focus] string city = 2; // [!code focus] string state = 3; // [!code focus] string postal_code = 4; // [!code focus] string country = 5; // [!code focus] } // [!code focus]"},{"id":"cli/breaking-changes/rules/message-no-delete::good::20","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; User user = 2; } ```","content":"Good message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::impact::21","title":"MESSAGE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with the deleted message cannot be deserialized **Generated Code:** Message classes/structs are removed, breaking client compilation **Field References:** Fields using the deleted me","content":"Impact **Wire Format:** Existing data with the deleted message cannot be deserialized **Generated Code:** Message classes/structs are removed, breaking client compilation **Field References:** Fields using the deleted message type become invalid **Nested Dependencies:** All messages referencing the deleted message break"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::22","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR after deletion Street: \"123 Main St\", City:","content":"Real-World Example **Client code breaks:** ```go // Before - this code works user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR after deletion Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::23","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.Address ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::24","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"name\": \"John Doe\", \"email\": \"john@example.com\", \"address\": { \"street\": \"123 Main St\", \"city\": \"New York\", \"country\": ","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"name\": \"John Doe\", \"email\": \"john@example.com\", \"address\": { \"street\": \"123 Main St\", \"city\": \"New York\", \"country\": \"USA\" } }"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::25","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After Address deletion - deserialization fails // Parser doesn't know how to handle \"address\" field ```","content":"Real-World Example // After Address deletion - deserialization fails // Parser doesn't know how to handle \"address\" field ```"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::26","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the message first:**","content":"Migration Strategy **Deprecate the message first:**"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::27","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using in new fields** and deprecate existing fields that use it:","content":"Migration Strategy **Stop using in new fields** and deprecate existing fields that use it:"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::28","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create replacement** with new structure if needed:","content":"Migration Strategy **Create replacement** with new structure if needed:"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::29","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/breaking-changes/rules/message-no-delete::refactoring-message-structure::30","title":"MESSAGE_NO_DELETE","section":"Refactoring Message Structure","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#refactoring-message-structure","headings":["Refactoring Message Structure"],"excerpt":"Refactoring Message Structure ```proto // Instead of deleting UserInfo and creating UserProfile message UserInfo { option deprecated = true; // Deprecate old string name = 1; string email = 2; }","content":"Refactoring Message Structure ```proto // Instead of deleting UserInfo and creating UserProfile message UserInfo { option deprecated = true; // Deprecate old string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::refactoring-message-structure::31","title":"MESSAGE_NO_DELETE","section":"Refactoring Message Structure","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#refactoring-message-structure","headings":["Refactoring Message Structure"],"excerpt":"Refactoring Message Structure message UserProfile { // Create new alongside string full_name = 1; string email_address = 2; string phone = 3; // Better field organization } ```","content":"Refactoring Message Structure message UserProfile { // Create new alongside string full_name = 1; string email_address = 2; string phone = 3; // Better field organization } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::version-migration::32","title":"MESSAGE_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration ```proto // Clean approach - new package version package myapi.v2;","content":"Version Migration ```proto // Clean approach - new package version package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::version-migration::33","title":"MESSAGE_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration message User { // Redesigned message structure // No deprecated Address references } ```","content":"Version Migration message User { // Redesigned message structure // No deprecated Address references } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::0","title":"ONEOF_FIELD_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":[],"excerpt":"This rule checks that no fields are deleted from oneOf groups. Deleting a field from a oneOf breaks both wire format compatibility and generated code, as existing data may use the deleted oneOf option and client code dep","content":"This rule checks that no fields are deleted from oneOf groups. Deleting a field from a oneOf breaks both wire format compatibility and generated code, as existing data may use the deleted oneOf option and client code depends on the generated field types and accessor methods."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::1","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::2","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::3","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::4","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::5","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Deleted oneOf field - BREAKING! // string certificate = 5; // [!code -","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Deleted oneOf field - BREAKING! // string certificate = 5; // [!code --] Deleted oneOf field - BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::6","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Deleted oneOf field - BREAKING! // DateRange date_range = 4; // [!code --] Deleted oneOf field - BREAKING","content":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Deleted oneOf field - BREAKING! // DateRange date_range = 4; // [!code --] Deleted oneOf field - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::7","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested message oneOf field deletion:**","content":"More Examples **Nested message oneOf field deletion:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::8","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; CryptoPayment crypto = 4; // [!code --] Gift","content":"More Examples ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; CryptoPayment crypto = 4; // [!code --] GiftCardPayment gift_card = 5; // [!code --] } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::9","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto = 4; // BR","content":"More Examples // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto = 4; // BREAKING: deleted // GiftCardPayment gift_card = 5; // BREAKING: deleted } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::10","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the oneOf fields:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the oneOf fields:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::11","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] string certificate = 5 [deprecated = true]; // [!","content":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] string certificate = 5 [deprecated = true]; // [!code focus] } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::12","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3 [deprecated = true]; // [!code focus] DateRange date_range = 4 [deprecated = true]; // [!code focus] } } ```","content":"Good message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3 [deprecated = true]; // [!code focus] DateRange date_range = 4 [deprecated = true]; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::13","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good **Or add new oneOf fields while keeping old ones:** ```proto syntax = \"proto3\";","content":"Good **Or add new oneOf fields while keeping old ones:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::14","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Keep old field string certificate = 5 [depreca","content":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Keep old field string certificate = 5 [deprecated = true]; // [!code focus] // Keep old field OAuthCredentials oauth_v2 = 6; // [!code focus] // New structured approach CertificateCredentials cert_v2 = 7; // [!code focus] // New structured approach } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact::15","title":"ONEOF_FIELD_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with deleted oneOf fields cannot be deserialized properly **Generated Code:** OneOf field accessor methods are removed, breaking client compilation **Type Safety:** Generated oneOf w","content":"Impact **Wire Format:** Existing data with deleted oneOf fields cannot be deserialized properly **Generated Code:** OneOf field accessor methods are removed, breaking client compilation **Type Safety:** Generated oneOf wrapper types lose options, breaking switch statements **Business Logic:** Client code handling specific oneOf cases breaks"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::16","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::17","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set OAuth token (oneOf field) loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR after field deletion }","content":"Real-World Example // Set OAuth token (oneOf field) loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR after field deletion }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::18","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch on oneOf field types switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: ","content":"Real-World Example // Switch on oneOf field types switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: undefined type after deletion return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: undefined type after deletion return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::19","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::20","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server handling breaks:**","content":"Real-World Example **Server handling breaks:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::21","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"username\": \"user123\", \"oauth_token\": \"abc123xyz\" }","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"username\": \"user123\", \"oauth_token\": \"abc123xyz\" }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::22","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf field deletion // Data deserializes but oauth_token is lost or causes parsing errors // User authentication fails due to missing credential data ```","content":"Real-World Example // After oneOf field deletion // Data deserializes but oauth_token is lost or causes parsing errors // User authentication fails due to missing credential data ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::23","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate oneOf fields first:**","content":"Migration Strategy **Deprecate oneOf fields first:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::24","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new fields** if replacement is needed:","content":"Migration Strategy **Add new fields** if replacement is needed:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::25","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::26","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new fields:","content":"Migration Strategy **Migrate clients** to use new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::27","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve field numbers** after removal in next major version:","content":"Migration Strategy **Reserve field numbers** after removal in next major version:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::removing-unsupported-authentication-methods::28","title":"ONEOF_FIELD_NO_DELETE","section":"Removing Unsupported Authentication Methods","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#removing-unsupported-authentication-methods","headings":["Removing Unsupported Authentication Methods"],"excerpt":"Removing Unsupported Authentication Methods","content":"Removing Unsupported Authentication Methods"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs-other-deletions::29","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs Other Deletions","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs-other-deletions","headings":["OneOf Field Deletion vs Other Deletions"],"excerpt":"OneOf Field Deletion vs Other Deletions","content":"OneOf Field Deletion vs Other Deletions"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::different-from-regular-field-deletion::30","title":"ONEOF_FIELD_NO_DELETE","section":"Different from Regular Field Deletion","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#different-from-regular-field-deletion","headings":["Different from Regular Field Deletion"],"excerpt":"Different from Regular Field Deletion ```proto // Regular field deletion (also breaking) message User { string name = 1; // string email = 2; // BREAKING: regular field deletion }","content":"Different from Regular Field Deletion ```proto // Regular field deletion (also breaking) message User { string name = 1; // string email = 2; // BREAKING: regular field deletion }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::different-from-regular-field-deletion::31","title":"ONEOF_FIELD_NO_DELETE","section":"Different from Regular Field Deletion","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#different-from-regular-field-deletion","headings":["Different from Regular Field Deletion"],"excerpt":"Different from Regular Field Deletion // OneOf field deletion (breaks oneOf semantics) message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: oneOf field deletion } } ```","content":"Different from Regular Field Deletion // OneOf field deletion (breaks oneOf semantics) message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: oneOf field deletion } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact-on-generated-code::32","title":"ONEOF_FIELD_NO_DELETE","section":"Impact on Generated Code","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact-on-generated-code","headings":["Impact on Generated Code"],"excerpt":"Impact on Generated Code ```go // Regular field - simple accessor removed // user.GetEmail() // Method removed","content":"Impact on Generated Code ```go // Regular field - simple accessor removed // user.GetEmail() // Method removed"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact-on-generated-code::33","title":"ONEOF_FIELD_NO_DELETE","section":"Impact on Generated Code","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact-on-generated-code","headings":["Impact on Generated Code"],"excerpt":"Impact on Generated Code // OneOf field - wrapper type removed // *LoginRequest_OauthToken // Entire type removed // switch statement cases break completely ```","content":"Impact on Generated Code // OneOf field - wrapper type removed // *LoginRequest_OauthToken // Entire type removed // switch statement cases break completely ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::wire-format-considerations::34","title":"ONEOF_FIELD_NO_DELETE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations ```proto // OneOf fields share the same \"choice\" semantics // Removing a choice breaks clients that made that choice","content":"Wire Format Considerations ```proto // OneOf fields share the same \"choice\" semantics // Removing a choice breaks clients that made that choice"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::wire-format-considerations::35","title":"ONEOF_FIELD_NO_DELETE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations message Request { oneof data { string text = 1; // Choice A bytes binary = 2; // Choice B - if removed, clients using B break JsonData json = 3; // Choice C } } ```","content":"Wire Format Considerations message Request { oneof data { string text = 1; // Choice A bytes binary = 2; // Choice B - if removed, clients using B break JsonData json = 3; // Choice C } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::0","title":"ONEOF_FIELD_SAME_TYPE","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":[],"excerpt":"This rule checks that oneOf field types cannot be changed. Changing the type of a field within a oneOf breaks both wire format compatibility and generated code, as existing data contains the old type and client code expe","content":"This rule checks that oneOf field types cannot be changed. Changing the type of a field within a oneOf breaks both wire format compatibility and generated code, as existing data contains the old type and client code expects specific field types in oneOf wrapper structures."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Bad message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Bad message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Changed from string to int32 - BREAKING! string user_id = 3; // [!code --] Changed from int32 to string - BREAKING! string is","content":"Bad message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Changed from string to int32 - BREAKING! string user_id = 3; // [!code --] Changed from int32 to string - BREAKING! string is_premium = 4; // [!code --] Changed from bool to string - BREAKING! string date_range = 5; // [!code --] Changed from DateRange to string - BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Changed from string to EmailConfig - BREAKING! string phone_number = 2; // [!code --] Changed from int64 to string - BREAKING! stri","content":"Bad message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Changed from string to EmailConfig - BREAKING! string phone_number = 2; // [!code --] Changed from int64 to string - BREAKING! string webhook = 3; // [!code --] Changed from WebhookConfig to string - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::7","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Complex type changes:**","content":"More Examples **Complex type changes:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::8","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWalletInfo crypto = 4; } }","content":"More Examples ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWalletInfo crypto = 4; } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::9","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! message PaymentRequest { oneof payment_info { string credit_card = 1; // BREAKING: CreditCardInfo -> string PayPalInfo bank_account = 2; // BREAKING: BankAccountInfo -> PayP","content":"More Examples // After - ALL BREAKING CHANGES! message PaymentRequest { oneof payment_info { string credit_card = 1; // BREAKING: CreditCardInfo -> string PayPalInfo bank_account = 2; // BREAKING: BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // BREAKING: string -> PayPalInfo string crypto = 4; // BREAKING: CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good **Instead of changing type, add new oneOf field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing type, add new oneOf field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // [!code focus] // Keep original type int32 user_id = 3 [deprecated = true]; // [!code focus] // Keep original type ","content":"Good message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // [!code focus] // Keep original type int32 user_id = 3 [deprecated = true]; // [!code focus] // Keep original type bool is_premium = 4 [deprecated = true]; // [!code focus] // Keep original type DateRange date_range = 5 [deprecated = true]; // [!code focus] // Keep original type int32 category_id = 6; // [!code focus] // New field with desired type string user_identifier = 7; // [!code focus] // New field with desired type string premium_status = 8; // [!code focus] // New field with desired type string date_filter = 9; // [!code focus] // New field with desired type } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good **Or create a new oneOf group:** ```proto syntax = \"proto3\";","content":"Good **Or create a new oneOf group:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good message SearchRequest { string query = 1; oneof filter { option deprecated = true; // [!code focus] // Deprecate old oneOf string category = 2 [deprecated = true]; // [!code focus] int32 user_id = 3 [deprecated = tr","content":"Good message SearchRequest { string query = 1; oneof filter { option deprecated = true; // [!code focus] // Deprecate old oneOf string category = 2 [deprecated = true]; // [!code focus] int32 user_id = 3 [deprecated = true]; // [!code focus] bool is_premium = 4 [deprecated = true]; // [!code focus] DateRange date_range = 5 [deprecated = true]; // [!code focus] } oneof filter_v2 { // [!code focus] // New oneOf with correct types int32 category_id = 6; // [!code focus] string user_identifier = 7; // [!code focus] PremiumFilter premium_filter = 8; // [!code focus] TimeFilter time_filter = 9; // [!code focus] } // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::impact::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** OneOf wrapper types change, breaking client compilation **Type Safety:** Switch statements on oneOf types break wi","content":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** OneOf wrapper types change, breaking client compilation **Type Safety:** Switch statements on oneOf types break with compilation errors **Runtime Errors:** Type mismatches cause parsing failures for existing data"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set filter using oneOf (original types) searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // string type }","content":"Real-World Example // Set filter using oneOf (original types) searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // string type }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Handle filter types switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // string parameter case *myapi.SearchRequest_UserId: retu","content":"Real-World Example // Handle filter types switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // string parameter case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // int32 parameter default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After type change - compilation fails searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR: expects int32, not string }","content":"Real-World Example // After type change - compilation fails searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR: expects int32, not string }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch statement breaks switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR: Category is now int32 case *myapi.SearchRequ","content":"Real-World Example // Switch statement breaks switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR: Category is now int32 case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId is now string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server expects original types func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchR","content":"Real-World Example **Server implementation breaks:** ```go // Before - server expects original types func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryName := filter.Category // string return searchDatabase(\"category\", categoryName), nil case *SearchRequest_UserId: userId := filter.UserId // int32 return searchDatabase(\"user_id\", strconv.Itoa(int(userId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After type change - runtime errors func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryId := filter.Catego","content":"Real-World Example // After type change - runtime errors func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryId := filter.Category // now int32, but code expects string return searchDatabase(\"category\", categoryId), nil // ERROR: type mismatch case *SearchRequest_UserId: userIdStr := filter.UserId // now string, but conversion logic expects int32 userId, _ := strconv.Atoi(userIdStr) // Works but semantics changed return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data corruption:** ```json // Serialized data before type change { \"query\": \"golang jobs\", \"category\": \"engineering\" }","content":"Real-World Example **Existing data corruption:** ```json // Serialized data before type change { \"query\": \"golang jobs\", \"category\": \"engineering\" }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After changing category from string to int32 // Data cannot be deserialized - \"engineering\" is not a valid int32 // Results in parsing errors or data loss ```","content":"Real-World Example // After changing category from string to int32 // Data cannot be deserialized - \"engineering\" is not a valid int32 // Results in parsing errors or data loss ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new oneOf fields** with correct types:","content":"Migration Strategy **Add new oneOf fields** with correct types:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new fields:","content":"Migration Strategy **Migrate clients** to use new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Provide migration utilities** for data conversion:","content":"Migration Strategy **Provide migration utilities** for data conversion:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old fields** in next major version:","content":"Migration Strategy **Remove old fields** in next major version:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::type-change-compatibility-matrix::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Type Change Compatibility Matrix","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#type-change-compatibility-matrix","headings":["Type Change Compatibility Matrix"],"excerpt":"Type Change Compatibility Matrix","content":"Type Change Compatibility Matrix"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::never-compatible-always-breaking::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Never Compatible (Always Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#never-compatible-always-breaking","headings":["Never Compatible (Always Breaking)"],"excerpt":"Never Compatible (Always Breaking) From Type To Type Result ----------- --------- --------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING","content":"Never Compatible (Always Breaking) From Type To Type Result ----------- --------- --------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum int32 ❌ BREAKING"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::31","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact ```go // String to int32 change breaks wrapper types // Before: type SearchRequest_Category struct { Category string }","content":"Generated Code Impact ```go // String to int32 change breaks wrapper types // Before: type SearchRequest_Category struct { Category string }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::32","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // After: type SearchRequest_Category struct { Category int32 // Different type - compilation fails }","content":"Generated Code Impact // After: type SearchRequest_Category struct { Category int32 // Different type - compilation fails }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::33","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // All client code using SearchRequest_Category breaks ```","content":"Generated Code Impact // All client code using SearchRequest_Category breaks ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::wire-format-considerations::34","title":"ONEOF_FIELD_SAME_TYPE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations ```proto // OneOf fields in wire format are identified by field number // Type changes break deserialization even if field number stays same","content":"Wire Format Considerations ```proto // OneOf fields in wire format are identified by field number // Type changes break deserialization even if field number stays same"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::wire-format-considerations::35","title":"ONEOF_FIELD_SAME_TYPE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations message Request { oneof data { string text = 1; // Wire tag: 1, type: string // int32 text = 1; // Same wire tag, different type - BREAKING! } } ```","content":"Wire Format Considerations message Request { oneof data { string text = 1; // Wire tag: 1, type: string // int32 text = 1; // Same wire tag, different type - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::type-safe-validation-before-change::36","title":"ONEOF_FIELD_SAME_TYPE","section":"Type-Safe Validation (Before Change)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#type-safe-validation-before-change","headings":["Type-Safe Validation (Before Change)"],"excerpt":"Type-Safe Validation (Before Change)","content":"Type-Safe Validation (Before Change)"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::broken-validation-after-type-change::37","title":"ONEOF_FIELD_SAME_TYPE","section":"Broken Validation (After Type Change)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#broken-validation-after-type-change","headings":["Broken Validation (After Type Change)"],"excerpt":"Broken Validation (After Type Change)","content":"Broken Validation (After Type Change)"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::0","title":"ONEOF_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":[],"excerpt":"This rule checks that no oneOf fields are deleted from messages. Deleting a oneOf breaks both wire format compatibility and generated code, as existing data may use the oneOf structure and client code depends on the gene","content":"This rule checks that no oneOf fields are deleted from messages. Deleting a oneOf breaks both wire format compatibility and generated code, as existing data may use the oneOf structure and client code depends on the generated oneOf types and accessor methods."},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::1","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::2","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::3","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] } // [!code --","content":"Bad message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::4","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::5","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::6","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; // credentials oneof was deleted - BREAKING CHANGE! string password = 2; // Now regular fields string api_key = 3; // Lost exclusive semantics string oauth_token = 4; }","content":"Bad message LoginRequest { string username = 1; // credentials oneof was deleted - BREAKING CHANGE! string password = 2; // Now regular fields string api_key = 3; // Lost exclusive semantics string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::7","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message PaymentMethod { // method oneof was deleted - BREAKING CHANGE! CreditCard credit_card = 1; // Now all can be set simultaneously BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Bad message PaymentMethod { // method oneof was deleted - BREAKING CHANGE! CreditCard credit_card = 1; // Now all can be set simultaneously BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::8","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::9","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested oneOf deletion:**","content":"More Examples **Nested oneOf deletion:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::10","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2; // [!code --] string slack_id = 3; // [","content":"More Examples ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2; // [!code --] string slack_id = 3; // [!code --] } // [!code --] } ContactInfo contact = 2; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::11","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof was deleted string email = 1; // No longer mutually exclusive string phone = 2; // Can set al","content":"More Examples // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof was deleted string email = 1; // No longer mutually exclusive string phone = 2; // Can set all fields now string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::12","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the oneOf:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the oneOf:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::13","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code ","content":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code focus] string oauth_token = 4 [deprecated = true]; // [!code focus] } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::14","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; // [!code focus] P","content":"Good message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; // [!code focus] PayPal paypal = 3 [deprecated = true]; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::15","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new structure:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new structure:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::16","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Old oneOf string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true","content":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Old oneOf string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code focus] string oauth_token = 4 [deprecated = true]; // [!code focus] } oneof auth_method { // [!code focus] // New oneOf with better design PasswordAuth password_auth = 5; // [!code focus] ApiKeyAuth api_auth = 6; // [!code focus] OAuthAuth oauth_auth = 7; // [!code focus] } // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::impact::17","title":"ONEOF_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** OneOf semantics are lost - fields are no longer mutually exclusive **Generated Code:** OneOf accessor methods are removed, breaking client compilation **Business Logic:** Mutual exclusivity constr","content":"Impact **Wire Format:** OneOf semantics are lost - fields are no longer mutually exclusive **Generated Code:** OneOf accessor methods are removed, breaking client compilation **Business Logic:** Mutual exclusivity constraints are violated **Validation:** Client code expecting only one field to be set may break"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::18","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - oneOf provides mutual exclusivity loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Real-World Example **Client code breaks:** ```go // Before - oneOf provides mutual exclusivity loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::19","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set one of the credential options (oneOf semantics) loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Real-World Example // Set one of the credential options (oneOf semantics) loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::20","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check which credential type is set switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR after oneOf deletion return authenticatePassword(cred.Password) case *myap","content":"Real-World Example // Check which credential type is set switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR after oneOf deletion return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR after oneOf deletion return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::21","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::22","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - server validates oneOf semantics func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required","content":"Real-World Example **Server validation breaks:** ```go // Before - server validates oneOf semantics func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } // OneOf ensures only one credential type is set switch req.Credentials.(type) { case *LoginRequest_Password: return validatePassword(req.GetPassword()) case *LoginRequest_ApiKey: return validateApiKey(req.GetApiKey()) case *LoginRequest_OauthToken: return validateOAuthToken(req.GetOauthToken()) default: return errors.New(\"unknown credential type\") } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::23","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf deletion - validation logic breaks func validateLoginRequest(req *LoginRequest) error { // No more oneOf - multiple fields can be set! credCount := 0 if req.Password != \"\" { credCount++ ","content":"Real-World Example // After oneOf deletion - validation logic breaks func validateLoginRequest(req *LoginRequest) error { // No more oneOf - multiple fields can be set! credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ } if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") // Manual check needed! } // Lost type safety - need manual checks if req.Password != \"\" { return validatePassword(req.Password) } // ... more manual validation } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::24","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Business logic problems:** ```go // Before - oneOf guarantees mutual exclusivity payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, } // Impossi","content":"Real-World Example **Business logic problems:** ```go // Before - oneOf guarantees mutual exclusivity payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, } // Impossible to set multiple payment methods simultaneously"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::25","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf deletion - business logic can break payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Both set! Logic breaks! } ```","content":"Real-World Example // After oneOf deletion - business logic can break payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Both set! Logic breaks! } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::26","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the oneOf and all its fields:**","content":"Migration Strategy **Deprecate the oneOf and all its fields:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::27","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create new structure** if needed:","content":"Migration Strategy **Create new structure** if needed:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::28","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both during transition:","content":"Migration Strategy **Update server code** to handle both during transition:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::29","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new structure:","content":"Migration Strategy **Migrate clients** to use new structure:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::30","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old oneOf** in next major version","content":"Migration Strategy **Remove old oneOf** in next major version"},{"id":"cli/breaking-changes/rules/oneof-no-delete::replacing-oneof-with-regular-fields::31","title":"ONEOF_NO_DELETE","section":"Replacing OneOf with Regular Fields","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#replacing-oneof-with-regular-fields","headings":["Replacing OneOf with Regular Fields"],"excerpt":"Replacing OneOf with Regular Fields ```proto // Instead of removing oneOf structure entirely message SearchRequest { // Don't delete oneOf - breaks mutual exclusivity string text_query = 1; // BREAKING: was in oneOf int3","content":"Replacing OneOf with Regular Fields ```proto // Instead of removing oneOf structure entirely message SearchRequest { // Don't delete oneOf - breaks mutual exclusivity string text_query = 1; // BREAKING: was in oneOf int32 user_id = 2; // BREAKING: was in oneOf string category = 3; // BREAKING: was in oneOf }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::replacing-oneof-with-regular-fields::32","title":"ONEOF_NO_DELETE","section":"Replacing OneOf with Regular Fields","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#replacing-oneof-with-regular-fields","headings":["Replacing OneOf with Regular Fields"],"excerpt":"Replacing OneOf with Regular Fields // Keep oneOf, add new fields if needed message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]","content":"Replacing OneOf with Regular Fields // Keep oneOf, add new fields if needed message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } // Add new non-exclusive fields if that's the intent string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::simplifying-message-structure::33","title":"ONEOF_NO_DELETE","section":"Simplifying Message Structure","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#simplifying-message-structure","headings":["Simplifying Message Structure"],"excerpt":"Simplifying Message Structure ```proto // Instead of flattening oneOf structure message NotificationSettings { // Don't delete oneOf - loses type safety string email = 1; // BREAKING: was in oneOf string phone = 2; // BR","content":"Simplifying Message Structure ```proto // Instead of flattening oneOf structure message NotificationSettings { // Don't delete oneOf - loses type safety string email = 1; // BREAKING: was in oneOf string phone = 2; // BREAKING: was in oneOf string webhook_url = 3; // BREAKING: was in oneOf }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::simplifying-message-structure::34","title":"ONEOF_NO_DELETE","section":"Simplifying Message Structure","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#simplifying-message-structure","headings":["Simplifying Message Structure"],"excerpt":"Simplifying Message Structure // Keep oneOf for type safety message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Simplifying Message Structure // Keep oneOf for type safety message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::35","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration ```proto // When migrating from proto2 to proto3 // Don't lose oneOf semantics during migration","content":"Proto Syntax Migration ```proto // When migrating from proto2 to proto3 // Don't lose oneOf semantics during migration"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::36","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Proto Syntax Migration // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::37","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration // proto3 - keep oneOf structure message Request { string name = 1; oneof data { // Don't delete this! string text = 2; int32 number = 3; } } ```","content":"Proto Syntax Migration // proto3 - keep oneOf structure message Request { string name = 1; oneof data { // Don't delete this! string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::what-oneof-provides::38","title":"ONEOF_NO_DELETE","section":"What OneOf Provides","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#what-oneof-provides","headings":["What OneOf Provides"],"excerpt":"What OneOf Provides **Mutual Exclusivity**: Only one field can be set at a time **Type Safety**: Generated code enforces single choice **Clear Intent**: API design expresses \"choose one\" semantics **Efficient Wire Format","content":"What OneOf Provides **Mutual Exclusivity**: Only one field can be set at a time **Type Safety**: Generated code enforces single choice **Clear Intent**: API design expresses \"choose one\" semantics **Efficient Wire Format**: Only selected field is serialized"},{"id":"cli/breaking-changes/rules/oneof-no-delete::whats-lost-when-deleted::39","title":"ONEOF_NO_DELETE","section":"What's Lost When Deleted","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#whats-lost-when-deleted","headings":["What's Lost When Deleted"],"excerpt":"What's Lost When Deleted **Business Logic**: No enforcement of mutual exclusivity **Generated Code**: No oneOf wrapper types or methods **Validation**: Manual checks needed for exclusivity **API Clarity**: Intent of \"cho","content":"What's Lost When Deleted **Business Logic**: No enforcement of mutual exclusivity **Generated Code**: No oneOf wrapper types or methods **Validation**: Manual checks needed for exclusivity **API Clarity**: Intent of \"choose one\" is lost"},{"id":"cli/breaking-changes/rules/oneof-no-delete::generated-code-impact::40","title":"ONEOF_NO_DELETE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact ```go // With oneOf - type safe type LoginRequest struct { Username string // Types that are assignable to Credentials: // *LoginRequest_Password // *LoginRequest_ApiKey Credentials isLoginRequest_C","content":"Generated Code Impact ```go // With oneOf - type safe type LoginRequest struct { Username string // Types that are assignable to Credentials: // *LoginRequest_Password // *LoginRequest_ApiKey Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::generated-code-impact::41","title":"ONEOF_NO_DELETE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // Without oneOf - no type safety type LoginRequest struct { Username string Password string // All can be set simultaneously ApiKey string // No mutual exclusivity OauthToken string } ```","content":"Generated Code Impact // Without oneOf - no type safety type LoginRequest struct { Username string Password string // All can be set simultaneously ApiKey string // No mutual exclusivity OauthToken string } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::0","title":"RPC_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":[],"excerpt":"This rule checks that no RPC methods are deleted from services. Deleting an RPC method breaks both generated code and client applications that call the method.","content":"This rule checks that no RPC methods are deleted from services. Deleting an RPC method breaks both generated code and client applications that call the method."},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::1","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::2","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); // [!code -","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); // [!code --] } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::3","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::4","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC was deleted - BREAKING CHANGE! } ```","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC was deleted - BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::good::5","title":"RPC_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::good::6","title":"RPC_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) { option de","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) { option deprecated = true; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::impact::7","title":"RPC_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** RPC method stubs are removed, breaking client compilation **Client Applications:** Existing calls to the RPC fail to compile **Runtime:** gRPC clients lose method definition","content":"Impact **Generated Code:** RPC method stubs are removed, breaking client compilation **Client Applications:** Existing calls to the RPC fail to compile **Runtime:** gRPC clients lose method definition"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::8","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::9","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Return error from implementation** indicating method is no longer supported","content":"Migration Strategy **Return error from implementation** indicating method is no longer supported"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::10","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove in next major version** after clients have migrated","content":"Migration Strategy **Remove in next major version** after clients have migrated"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::0","title":"RPC_SAME_REQUEST_TYPE","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":[],"excerpt":"This rule checks that RPC methods maintain the same request message type. Changing an RPC's request type breaks both wire format compatibility and generated code, as clients expect specific message structures when callin","content":"This rule checks that RPC methods maintain the same request message type. Changing an RPC's request type breaks both wire format compatibility and generated code, as clients expect specific message structures when calling the method."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::1","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::2","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::3","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserRequest { string user_id = 1; }","content":"Bad message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::4","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Bad message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::5","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::6","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Changed request type rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Changed request type }","content":"Bad service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Changed request type rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Changed request type }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::7","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserRequestV2 { // [!code --] Different message type string id = 1; bool include_profile = 2; }","content":"Bad message GetUserRequestV2 { // [!code --] Different message type string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::8","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message UserUpdateRequest { // [!code --] Different message type string id = 1; UserProfile profile = 2; } ```","content":"Bad message UserUpdateRequest { // [!code --] Different message type string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::9","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Cross-package type changes:**","content":"More Examples **Cross-package type changes:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::10","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"common/user.proto\";","content":"More Examples ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::11","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::12","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"More Examples // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::13","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Different package } ```","content":"More Examples service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Different package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::14","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good **Instead of changing request type, version the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing request type, version the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::15","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // New RPC metho","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // New RPC method rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // New RPC method }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::16","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good // Keep old messages for backward compatibility message GetUserRequest { string user_id = 1; }","content":"Good // Keep old messages for backward compatibility message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::17","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good // Add new messages for enhanced functionality message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Good // Add new messages for enhanced functionality message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::18","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good **Or create a new service version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new service version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::19","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::20","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::21","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good message GetUserRequest { // [!code focus] string id = 1; // [!code focus] // Improved field names bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Good message GetUserRequest { // [!code focus] string id = 1; // [!code focus] // Improved field names bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::impact::22","title":"RPC_SAME_REQUEST_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing client requests cannot be deserialized by new server **Generated Code:** Client stubs expect different request message types, breaking compilation **gRPC Calls:** Method signatures change","content":"Impact **Wire Format:** Existing client requests cannot be deserialized by new server **Generated Code:** Client stubs expect different request message types, breaking compilation **gRPC Calls:** Method signatures change in generated client code **Runtime Errors:** Type mismatches cause RPC call failures"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::23","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::24","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After request type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: type not found UserId: \"user123\", // ERROR:","content":"Real-World Example // After request type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: type not found UserId: \"user123\", // ERROR: field not found })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::25","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Must use new type: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", // Different field name IncludeProfile: true, // New required field }) ```","content":"Real-World Example // Must use new type: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", // Different field name IncludeProfile: true, // New required field }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::26","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server expects GetUserRequest func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ","content":"Real-World Example **Server implementation breaks:** ```go // Before - server expects GetUserRequest func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // This field exists // ... implementation }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::27","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - server must handle GetUserRequestV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id // Different field name includeProfile :","content":"Real-World Example // After - server must handle GetUserRequestV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id // Different field name includeProfile := req.IncludeProfile // New field to handle // ... implementation must change } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::28","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new RPC method** with improved request type:","content":"Migration Strategy **Add new RPC method** with improved request type:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::29","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Implement both methods** on server during transition:","content":"Migration Strategy **Implement both methods** on server during transition:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::30","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new RPC method:","content":"Migration Strategy **Migrate clients** to use new RPC method:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::31","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old RPC** in next major version:","content":"Migration Strategy **Remove old RPC** in next major version:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::adding-required-fields::32","title":"RPC_SAME_REQUEST_TYPE","section":"Adding Required Fields","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#adding-required-fields","headings":["Adding Required Fields"],"excerpt":"Adding Required Fields ```proto // Instead of modifying existing request message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING: new required field }","content":"Adding Required Fields ```proto // Instead of modifying existing request message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING: new required field }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::adding-required-fields::33","title":"RPC_SAME_REQUEST_TYPE","section":"Adding Required Fields","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#adding-required-fields","headings":["Adding Required Fields"],"excerpt":"Adding Required Fields // Add new RPC method message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; // Safe in new method } ```","content":"Adding Required Fields // Add new RPC method message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; // Safe in new method } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::restructuring-request-data::34","title":"RPC_SAME_REQUEST_TYPE","section":"Restructuring Request Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#restructuring-request-data","headings":["Restructuring Request Data"],"excerpt":"Restructuring Request Data ```proto // Instead of changing field structure message UpdateUserRequest { UserProfile profile = 1; // BREAKING: was individual fields }","content":"Restructuring Request Data ```proto // Instead of changing field structure message UpdateUserRequest { UserProfile profile = 1; // BREAKING: was individual fields }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::restructuring-request-data::35","title":"RPC_SAME_REQUEST_TYPE","section":"Restructuring Request Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#restructuring-request-data","headings":["Restructuring Request Data"],"excerpt":"Restructuring Request Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Restructuring Request Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::package-migrations::36","title":"RPC_SAME_REQUEST_TYPE","section":"Package Migrations","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#package-migrations","headings":["Package Migrations"],"excerpt":"Package Migrations ```proto // Instead of changing import packages import \"v2/messages.proto\"; // BREAKING: different package","content":"Package Migrations ```proto // Instead of changing import packages import \"v2/messages.proto\"; // BREAKING: different package"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::package-migrations::37","title":"RPC_SAME_REQUEST_TYPE","section":"Package Migrations","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#package-migrations","headings":["Package Migrations"],"excerpt":"Package Migrations // Keep old RPC, add new one rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Package Migrations // Keep old RPC, add new one rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::0","title":"RPC_SAME_RESPONSE_TYPE","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":[],"excerpt":"This rule checks that RPC methods maintain the same response message type. Changing an RPC's response type breaks both wire format compatibility and generated code, as clients expect specific message structures when rece","content":"This rule checks that RPC methods maintain the same response message type. Changing an RPC's response type breaks both wire format compatibility and generated code, as clients expect specific message structures when receiving responses from the method."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Bad message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Bad message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Changed response type rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Changed response type }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Changed response type rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Changed response type }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserResponseV2 { // [!code --] Different message type string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Bad message GetUserResponseV2 { // [!code --] Different message type string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message UserUpdateResponse { // [!code --] Different message type UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Bad message UserUpdateResponse { // [!code --] Different message type UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::9","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Cross-package type changes:**","content":"More Examples **Cross-package type changes:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::10","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"common/responses.proto\";","content":"More Examples ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::11","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::12","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"More Examples // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::13","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Different package } ```","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Different package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good **Instead of changing response type, version the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing response type, version the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // New RPC metho","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // New RPC method rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // New RPC method }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good // Keep old messages for backward compatibility message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Good // Keep old messages for backward compatibility message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good // Add new messages for enhanced functionality message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus]","content":"Good // Add new messages for enhanced functionality message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good **Or create a new service version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new service version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good message GetUserResponse { // [!code focus] string id = 1; // [!code focus] // Improved field names UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Good message GetUserResponse { // [!code focus] string id = 1; // [!code focus] // Improved field names UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::impact::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Server responses cannot be deserialized by existing clients **Generated Code:** Client stubs expect different response message types, breaking compilation **gRPC Calls:** Method signatures change ","content":"Impact **Wire Format:** Server responses cannot be deserialized by existing clients **Generated Code:** Client stubs expect different response message types, breaking compilation **gRPC Calls:** Method signatures change in generated client code **Runtime Errors:** Type mismatches cause RPC response handling failures"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return","content":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Access response fields userID := resp.UserId // This field exists name := resp.Name // This field exists","content":"Real-World Example // Access response fields userID := resp.UserId // This field exists name := resp.Name // This field exists"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After response type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Real-World Example // After response type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Access response fields - COMPILATION ERRORS userID := resp.UserId // ERROR: field not found name := resp.Name // ERROR: field not found","content":"Real-World Example // Access response fields - COMPILATION ERRORS userID := resp.UserId // ERROR: field not found name := resp.Name // ERROR: field not found"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Must use new fields: userID := resp.Id // Different field name profile := resp.Profile // New structure permissions := resp.Permissions // New field ```","content":"Real-World Example // Must use new fields: userID := resp.Id // Different field name profile := resp.Profile // New structure permissions := resp.Permissions // New field ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server returns GetUserResponse func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse","content":"Real-World Example **Server implementation breaks:** ```go // Before - server returns GetUserResponse func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"user123\", Name: \"John Doe\", Email: \"john@example.com\", }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - server must return GetUserResponseV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", // Different f","content":"Real-World Example // After - server must return GetUserResponseV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", // Different field name Profile: &UserProfile{ // New structure required Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, // New field to populate }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new RPC method** with improved response type:","content":"Migration Strategy **Add new RPC method** with improved response type:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Implement both methods** on server during transition:","content":"Migration Strategy **Implement both methods** on server during transition:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new RPC method:","content":"Migration Strategy **Migrate clients** to use new RPC method:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old RPC** in next major version:","content":"Migration Strategy **Remove old RPC** in next major version:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::adding-fields-to-response::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Adding Fields to Response","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#adding-fields-to-response","headings":["Adding Fields to Response"],"excerpt":"Adding Fields to Response ```proto // Instead of modifying existing response message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING: new required field }","content":"Adding Fields to Response ```proto // Instead of modifying existing response message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING: new required field }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::adding-fields-to-response::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Adding Fields to Response","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#adding-fields-to-response","headings":["Adding Fields to Response"],"excerpt":"Adding Fields to Response // Add new RPC method message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; // Safe in new method } ```","content":"Adding Fields to Response // Add new RPC method message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; // Safe in new method } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::restructuring-response-data::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Restructuring Response Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#restructuring-response-data","headings":["Restructuring Response Data"],"excerpt":"Restructuring Response Data ```proto // Instead of changing field structure message UpdateUserResponse { UserDetails details = 1; // BREAKING: was individual fields }","content":"Restructuring Response Data ```proto // Instead of changing field structure message UpdateUserResponse { UserDetails details = 1; // BREAKING: was individual fields }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::restructuring-response-data::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Restructuring Response Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#restructuring-response-data","headings":["Restructuring Response Data"],"excerpt":"Restructuring Response Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Restructuring Response Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::error-handling-changes::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Error Handling Changes","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#error-handling-changes","headings":["Error Handling Changes"],"excerpt":"Error Handling Changes ```proto // Instead of changing error structure message CreateUserResponse { ErrorDetails error = 1; // BREAKING: different error format }","content":"Error Handling Changes ```proto // Instead of changing error structure message CreateUserResponse { ErrorDetails error = 1; // BREAKING: different error format }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::error-handling-changes::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Error Handling Changes","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#error-handling-changes","headings":["Error Handling Changes"],"excerpt":"Error Handling Changes // Keep old RPC, add new one rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Error Handling Changes // Keep old RPC, add new one rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::response-format-migration::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Response Format Migration","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#response-format-migration","headings":["Response Format Migration"],"excerpt":"Response Format Migration ```proto // Instead of changing from simple to complex response message GetUserResponse { // BREAKING: changed from simple fields to nested structure UserData data = 1; }","content":"Response Format Migration ```proto // Instead of changing from simple to complex response message GetUserResponse { // BREAKING: changed from simple fields to nested structure UserData data = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::response-format-migration::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Response Format Migration","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#response-format-migration","headings":["Response Format Migration"],"excerpt":"Response Format Migration // Provide both formats during transition rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse","content":"Response Format Migration // Provide both formats during transition rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::0","title":"SERVICE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":[],"excerpt":"This rule checks that no services are deleted from proto files. Deleting a service breaks both generated code and client applications that depend on the service.","content":"This rule checks that no services are deleted from proto files. Deleting a service breaks both generated code and client applications that depend on the service."},{"id":"cli/breaking-changes/rules/service-no-delete::bad::1","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::2","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::3","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Bad service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::4","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::5","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::6","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad // OrderService was deleted - BREAKING CHANGE! ```","content":"Bad // OrderService was deleted - BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::good::7","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the service:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the service:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::good::8","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::good::9","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Good service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/service-no-delete::impact::10","title":"SERVICE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Service classes/interfaces are removed, breaking client compilation **Client Applications:** Existing client code fails to compile **Runtime:** gRPC clients lose service definition","content":"Impact **Generated Code:** Service classes/interfaces are removed, breaking client compilation **Client Applications:** Existing client code fails to compile **Runtime:** gRPC clients lose service definition"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::11","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::12","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Notify clients** about deprecation timeline","content":"Migration Strategy **Notify clients** about deprecation timeline"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::13","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/configuration/configuration::top::0","title":"EasyP Configuration Reference","path":"/docs/guide/cli/configuration/configuration","headings":[],"excerpt":"EasyP can be configured through CLI flags, environment variables, and configuration files. This guide covers all configuration options available in EasyP.","content":"EasyP can be configured through CLI flags, environment variables, and configuration files. This guide covers all configuration options available in EasyP."},{"id":"cli/configuration/configuration::global-flags::1","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Available for all commands:","content":"Global Flags Available for all commands:"},{"id":"cli/configuration/configuration::global-flags::2","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --cfg -c EASYP_CFG Configuration file path easyp.yaml --config EASYP_CFG Alias for --cfg easyp.yaml --debug -d ","content":"Global Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --cfg -c EASYP_CFG Configuration file path easyp.yaml --config EASYP_CFG Alias for --cfg easyp.yaml --debug -d EASYP_DEBUG Enable debug mode false --format -f EASYP_FORMAT Output format for commands that support multiple formats (text/json) command-specific default"},{"id":"cli/configuration/configuration::global-flags::3","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags **Examples:** ```bash Use custom config file easyp --cfg production.easyp.yaml lint","content":"Global Flags **Examples:** ```bash Use custom config file easyp --cfg production.easyp.yaml lint"},{"id":"cli/configuration/configuration::global-flags::4","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Enable debug logging easyp --debug lint","content":"Global Flags Enable debug logging easyp --debug lint"},{"id":"cli/configuration/configuration::global-flags::5","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Short form easyp -c custom.yaml -d lint ```","content":"Global Flags Short form easyp -c custom.yaml -d lint ```"},{"id":"cli/configuration/configuration::command-specific-flags::6","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Lint command:**","content":"Command-Specific Flags **Lint command:**"},{"id":"cli/configuration/configuration::command-specific-flags::7","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Base directory for file search Current working directory","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Base directory for file search Current working directory --format -f EASYP_FORMAT Uses global format flag (text/json) Inherits global default"},{"id":"cli/configuration/configuration::command-specific-flags::8","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Lint specific directory easyp lint --path proto/","content":"Command-Specific Flags **Examples:** ```bash Lint specific directory easyp lint --path proto/"},{"id":"cli/configuration/configuration::command-specific-flags::9","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Lint from subdirectory with proper import resolution easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint from subdirectory with proper import resolution easyp lint --root src/IPC/Contracts --path ."},{"id":"cli/configuration/configuration::command-specific-flags::10","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags JSON output format easyp --format json lint # global flag","content":"Command-Specific Flags JSON output format easyp --format json lint # global flag"},{"id":"cli/configuration/configuration::command-specific-flags::11","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Combined flags easyp -f json lint -p proto/ ```","content":"Command-Specific Flags Combined flags easyp -f json lint -p proto/ ```"},{"id":"cli/configuration/configuration::command-specific-flags::12","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Generate command:**","content":"Command-Specific Flags **Generate command:**"},{"id":"cli/configuration/configuration::command-specific-flags::13","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Directory path with proto files to generate . --root -r Base direc","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Directory path with proto files to generate . --root -r Base directory for file search Current working directory"},{"id":"cli/configuration/configuration::command-specific-flags::14","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Generate from specific path easyp generate --path api/","content":"Command-Specific Flags **Examples:** ```bash Generate from specific path easyp generate --path api/"},{"id":"cli/configuration/configuration::command-specific-flags::15","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Generate from subdirectory with proper import resolution easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate from subdirectory with proper import resolution easyp generate --root src/IPC/Contracts --path ."},{"id":"cli/configuration/configuration::command-specific-flags::16","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Using environment variable EASYP_ROOT_GENERATE_PATH=proto/ easyp generate ```","content":"Command-Specific Flags Using environment variable EASYP_ROOT_GENERATE_PATH=proto/ easyp generate ```"},{"id":"cli/configuration/configuration::command-specific-flags::17","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Breaking command:**","content":"Command-Specific Flags **Breaking command:**"},{"id":"cli/configuration/configuration::command-specific-flags::18","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --against Git ref to compare against master --path -p Directory path to check . --format -f EASYP_FOR","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --against Git ref to compare against master --path -p Directory path to check . --format -f EASYP_FORMAT Uses global format flag (text/json) Inherits global default"},{"id":"cli/configuration/configuration::command-specific-flags::19","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Check against main branch easyp breaking --against main","content":"Command-Specific Flags **Examples:** ```bash Check against main branch easyp breaking --against main"},{"id":"cli/configuration/configuration::command-specific-flags::20","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Check specific directory against develop branch easyp breaking --against develop --path proto/","content":"Command-Specific Flags Check specific directory against develop branch easyp breaking --against develop --path proto/"},{"id":"cli/configuration/configuration::command-specific-flags::21","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags JSON output easyp --format json breaking --against main # global flag ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # global flag ```"},{"id":"cli/configuration/configuration::command-specific-flags::22","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Init command:**","content":"Command-Specific Flags **Init command:**"},{"id":"cli/configuration/configuration::command-specific-flags::23","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --dir -d EASYP_INIT_DIR Directory to initialize .","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --dir -d EASYP_INIT_DIR Directory to initialize ."},{"id":"cli/configuration/configuration::command-specific-flags::24","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Initialize current directory easyp init","content":"Command-Specific Flags **Examples:** ```bash Initialize current directory easyp init"},{"id":"cli/configuration/configuration::command-specific-flags::25","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Initialize specific directory easyp init --dir proto-project/ ```","content":"Command-Specific Flags Initialize specific directory easyp init --dir proto-project/ ```"},{"id":"cli/configuration/configuration::command-specific-flags::26","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags easyp init is interactive: If buf.yml/buf.yaml exists in the target directory root, it asks whether to migrate from Buf. If easyp.yaml already exists, it asks for overwrite confirmation.","content":"Command-Specific Flags easyp init is interactive: If buf.yml/buf.yaml exists in the target directory root, it asks whether to migrate from Buf. If easyp.yaml already exists, it asks for overwrite confirmation."},{"id":"cli/configuration/configuration::command-specific-flags::27","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Validate-config command:**","content":"Command-Specific Flags **Validate-config command:**"},{"id":"cli/configuration/configuration::command-specific-flags::28","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Configuration file path easyp.yaml --format (global) -f EASYP_FORMAT Output for","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Configuration file path easyp.yaml --format (global) -f EASYP_FORMAT Output format for commands that support multiple formats (json or text) command-specific (json for validate-config)"},{"id":"cli/configuration/configuration::command-specific-flags::29","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Validate default config with JSON output (exit 0 when no errors) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Validate default config with JSON output (exit 0 when no errors) easyp validate-config"},{"id":"cli/configuration/configuration::command-specific-flags::30","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Validate a different file with text output (global --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Validate a different file with text output (global --format) easyp --format text validate-config --config example.easyp.yaml ```"},{"id":"cli/configuration/configuration::command-specific-flags::31","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Package management commands:**","content":"Command-Specific Flags **Package management commands:**"},{"id":"cli/configuration/configuration::easyp-mod-download::32","title":"EasyP Configuration Reference","section":"easyp mod download","path":"/docs/guide/cli/configuration/configuration#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Downloads dependencies based on lock file priority:","content":"easyp mod download Downloads dependencies based on lock file priority:"},{"id":"cli/configuration/configuration::easyp-mod-download::33","title":"EasyP Configuration Reference","section":"easyp mod download","path":"/docs/guide/cli/configuration/configuration#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **If easyp.lock exists** - downloads exact versions from lock file **If easyp.lock is missing** - downloads versions from easyp.yaml and creates easyp.lock","content":"easyp mod download **If easyp.lock exists** - downloads exact versions from lock file **If easyp.lock is missing** - downloads versions from easyp.yaml and creates easyp.lock"},{"id":"cli/configuration/configuration::easyp-mod-update::34","title":"EasyP Configuration Reference","section":"easyp mod update","path":"/docs/guide/cli/configuration/configuration#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Always downloads dependencies from easyp.yaml, ignoring existing lock file:","content":"easyp mod update Always downloads dependencies from easyp.yaml, ignoring existing lock file:"},{"id":"cli/configuration/configuration::easyp-mod-update::35","title":"EasyP Configuration Reference","section":"easyp mod update","path":"/docs/guide/cli/configuration/configuration#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update **Ignores easyp.lock** completely **Downloads versions from easyp.yaml** **Creates/updates easyp.lock** with new versions","content":"easyp mod update **Ignores easyp.lock** completely **Downloads versions from easyp.yaml** **Creates/updates easyp.lock** with new versions"},{"id":"cli/configuration/configuration::easyp-mod-vendor::36","title":"EasyP Configuration Reference","section":"easyp mod vendor","path":"/docs/guide/cli/configuration/configuration#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Copies proto files from dependencies to local vendor/ directory (similar to go mod vendor).","content":"easyp mod vendor Copies proto files from dependencies to local vendor/ directory (similar to go mod vendor)."},{"id":"cli/configuration/configuration::easyp-mod-vendor::37","title":"EasyP Configuration Reference","section":"easyp mod vendor","path":"/docs/guide/cli/configuration/configuration#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor No additional flags. Uses global --cfg flag for configuration.","content":"easyp mod vendor No additional flags. Uses global --cfg flag for configuration."},{"id":"cli/configuration/configuration::environment-variables::38","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables EasyP supports environment variables for configuration:","content":"Environment Variables EasyP supports environment variables for configuration:"},{"id":"cli/configuration/configuration::environment-variables::39","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Variable Description Default ---------- ------------- --------- EASYP_CFG Path to configuration file easyp.yaml EASYP_DEBUG Enable debug logging false EASYPPATH Cache and modules storage directory $","content":"Environment Variables Variable Description Default ---------- ------------- --------- EASYP_CFG Path to configuration file easyp.yaml EASYP_DEBUG Enable debug logging false EASYPPATH Cache and modules storage directory $HOME/.easyp EASYP_FORMAT Output format for supported commands (text/json). If not set, each command uses its own default. command-specific default EASYP_ROOT_GENERATE_PATH Root path for generate command . EASYP_INIT_DIR Directory for init command ."},{"id":"cli/configuration/configuration::environment-variables::40","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables **Examples:** ```bash Custom cache directory export EASYPPATH=/tmp/easyp-cache easyp mod download","content":"Environment Variables **Examples:** ```bash Custom cache directory export EASYPPATH=/tmp/easyp-cache easyp mod download"},{"id":"cli/configuration/configuration::environment-variables::41","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Debug mode via environment export EASYP_DEBUG=true easyp lint","content":"Environment Variables Debug mode via environment export EASYP_DEBUG=true easyp lint"},{"id":"cli/configuration/configuration::environment-variables::42","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Custom config file export EASYP_CFG=config/easyp.yaml easyp generate ```","content":"Environment Variables Custom config file export EASYP_CFG=config/easyp.yaml easyp generate ```"},{"id":"cli/configuration/configuration::configuration-file::43","title":"EasyP Configuration Reference","section":"Configuration File","path":"/docs/guide/cli/configuration/configuration#configuration-file","headings":["Configuration File"],"excerpt":"Configuration File The easyp.yaml file is the main configuration file for EasyP, defining how your proto files are linted, generated, and managed. This file is typically placed at the root of your project alongside your ","content":"Configuration File The easyp.yaml file is the main configuration file for EasyP, defining how your proto files are linted, generated, and managed. This file is typically placed at the root of your project alongside your proto files."},{"id":"cli/configuration/configuration::configuration-format::44","title":"EasyP Configuration Reference","section":"Configuration Format","path":"/docs/guide/cli/configuration/configuration#configuration-format","headings":["Configuration Format"],"excerpt":"Configuration Format EasyP supports both YAML and JSON configuration formats:","content":"Configuration Format EasyP supports both YAML and JSON configuration formats:"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::45","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration EasyP supports environment variable expansion directly in the easyp.yaml configuration file. This allows you to use environment variables for dynamic configuration values.","content":"Environment Variables in Configuration EasyP supports environment variable expansion directly in the easyp.yaml configuration file. This allows you to use environment variables for dynamic configuration values."},{"id":"cli/configuration/configuration::environment-variables-in-configuration::46","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Example with all supported features:** ```yaml deps: # Basic expansion: ${VAR} - expands to the value of VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Default value: ${VAR:-def","content":"Environment Variables in Configuration **Example with all supported features:** ```yaml deps: # Basic expansion: ${VAR} - expands to the value of VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Default value: ${VAR:-default} - uses default if VAR is unset or empty - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::47","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration generate: inputs: # Default value if INPUT_DIR is not set - directory: ${INPUT_DIR:-proto} plugins: - name: go # Basic expansion out: ${OUTPUT_DIR} opts: # Default value module: ${M","content":"Environment Variables in Configuration generate: inputs: # Default value if INPUT_DIR is not set - directory: ${INPUT_DIR:-proto} plugins: - name: go # Basic expansion out: ${OUTPUT_DIR} opts: # Default value module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Escaping: $$ becomes literal $, $${VAR} becomes literal ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Result: \"/tmp/${TEMP}/file\" (if BASE_DIR=/tmp) literal: \"$$\" # Result: \"$\" ```"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::48","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Supported syntax:** ${VAR} - expands to the value of VAR ${VAR:-default} - uses default if VAR is unset or empty ${VAR:=default} - uses default if VAR is unset or empty ${VAR-defa","content":"Environment Variables in Configuration **Supported syntax:** ${VAR} - expands to the value of VAR ${VAR:-default} - uses default if VAR is unset or empty ${VAR:=default} - uses default if VAR is unset or empty ${VAR-default} - uses default if VAR is unset (empty string is kept) $${VAR} or $$VAR - escapes to literal ${VAR} or $VAR $$ - escapes to literal $"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::49","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Note:** Environment variables are expanded before YAML parsing, so any ${STRING} pattern will be processed. Use $$ to escape dollar signs when you need literal values.","content":"Environment Variables in Configuration **Note:** Environment variables are expanded before YAML parsing, so any ${STRING} pattern will be processed. Use $$ to escape dollar signs when you need literal values."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Optional (legacy compatibility).** This field is accepted for backward compatibility and can be omitted in new configs.","content":"version **Optional (legacy compatibility).** This field is accepted for backward compatibility and can be omitted in new configs."},{"id":"cli/configuration/configuration::version::51","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Type:** string **Default:** omitted **Recommendation:** if you keep it, use v1alpha","content":"version **Type:** string **Default:** omitted **Recommendation:** if you keep it, use v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version The runtime behavior does not depend on this field.","content":"version The runtime behavior does not depend on this field."},{"id":"cli/configuration/configuration::lint::53","title":"EasyP Configuration Reference","section":"lint","path":"/docs/guide/cli/configuration/configuration#lint","headings":["lint"],"excerpt":"lint **Optional.** Configures proto file linting rules and behavior.","content":"lint **Optional.** Configures proto file linting rules and behavior."},{"id":"cli/configuration/configuration::lint::54","title":"EasyP Configuration Reference","section":"lint","path":"/docs/guide/cli/configuration/configuration#lint","headings":["lint"],"excerpt":"lint **Type:** object **Default:** Empty (no linting rules applied)","content":"lint **Type:** object **Default:** Empty (no linting rules applied)"},{"id":"cli/configuration/configuration::lintuse::55","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Optional.** Specifies which linter rules or rule categories to apply.","content":"lint.use **Optional.** Specifies which linter rules or rule categories to apply."},{"id":"cli/configuration/configuration::lintuse::56","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Type:** []string **Default:** [] (no rules)","content":"lint.use **Type:** []string **Default:** [] (no rules)"},{"id":"cli/configuration/configuration::lintuse::57","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Available categories:** MINIMAL - Essential package consistency checks BASIC - Naming conventions and common patterns DEFAULT - Additional recommended rules COMMENTS - Comment requirements UNARY_RPC - Streamin","content":"lint.use **Available categories:** MINIMAL - Essential package consistency checks BASIC - Naming conventions and common patterns DEFAULT - Additional recommended rules COMMENTS - Comment requirements UNARY_RPC - Streaming RPC restrictions"},{"id":"cli/configuration/configuration::lintuse::58","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Individual rules:** Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"lint.use **Individual rules:** Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/configuration/configuration::lintuse::59","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **MINIMAL:** DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY","content":"lint.use **MINIMAL:** DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY"},{"id":"cli/configuration/configuration::lintuse::60","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **BASIC:** ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PAC","content":"lint.use **BASIC:** ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNAKE_CASE PACKAGE_SAME_CSHARP_NAMESPACE PACKAGE_SAME_GO_PACKAGE PACKAGE_SAME_JAVA_MULTIPLE_FILES PACKAGE_SAME_JAVA_PACKAGE PACKAGE_SAME_PHP_NAMESPACE PACKAGE_SAME_RUBY_PACKAGE PACKAGE_SAME_SWIFT_PREFIX RPC_PASCAL_CASE SERVICE_PASCAL_CASE"},{"id":"cli/configuration/configuration::lintuse::61","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **DEFAULT:** ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX","content":"lint.use **DEFAULT:** ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX"},{"id":"cli/configuration/configuration::lintuse::62","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **COMMENTS:** COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE","content":"lint.use **COMMENTS:** COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE"},{"id":"cli/configuration/configuration::lintuse::63","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **UNARY_RPC:** RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING","content":"lint.use **UNARY_RPC:** RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING"},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::64","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix **Optional.** Specifies the required suffix for enum zero values.","content":"lint.enum_zero_value_suffix **Optional.** Specifies the required suffix for enum zero values."},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::65","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"lint.enum_zero_value_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::66","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix This enforces enum zero values like:","content":"lint.enum_zero_value_suffix This enforces enum zero values like:"},{"id":"cli/configuration/configuration::lintservice_suffix::67","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix **Optional.** Specifies the required suffix for service names.","content":"lint.service_suffix **Optional.** Specifies the required suffix for service names."},{"id":"cli/configuration/configuration::lintservice_suffix::68","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"Service\", \"API\", \"Svc\"","content":"lint.service_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"Service\", \"API\", \"Svc\""},{"id":"cli/configuration/configuration::lintservice_suffix::69","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix This enforces service names like:","content":"lint.service_suffix This enforces service names like:"},{"id":"cli/configuration/configuration::lintignore::70","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore **Optional.** Directories or files to exclude from all linting rules.","content":"lint.ignore **Optional.** Directories or files to exclude from all linting rules."},{"id":"cli/configuration/configuration::lintignore::71","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore **Type:** []string **Default:** []","content":"lint.ignore **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::lintignore::72","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore Paths are relative to the easyp.yaml file location. Supports glob patterns.","content":"lint.ignore Paths are relative to the easyp.yaml file location. Supports glob patterns."},{"id":"cli/configuration/configuration::lintexcept::73","title":"EasyP Configuration Reference","section":"lint.except","path":"/docs/guide/cli/configuration/configuration#lintexcept","headings":["lint.except"],"excerpt":"lint.except **Optional.** Disables specific rules globally across the entire project.","content":"lint.except **Optional.** Disables specific rules globally across the entire project."},{"id":"cli/configuration/configuration::lintexcept::74","title":"EasyP Configuration Reference","section":"lint.except","path":"/docs/guide/cli/configuration/configuration#lintexcept","headings":["lint.except"],"excerpt":"lint.except **Type:** []string **Default:** []","content":"lint.except **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::lintallow_comment_ignores::75","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores **Optional.** Enables inline comment-based rule ignoring within proto files.","content":"lint.allow_comment_ignores **Optional.** Enables inline comment-based rule ignoring within proto files."},{"id":"cli/configuration/configuration::lintallow_comment_ignores::76","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores **Type:** boolean **Default:** false","content":"lint.allow_comment_ignores **Type:** boolean **Default:** false"},{"id":"cli/configuration/configuration::lintallow_comment_ignores::77","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores When enabled, allows comments like:","content":"lint.allow_comment_ignores When enabled, allows comments like:"},{"id":"cli/configuration/configuration::lintignore_only::78","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Optional.** Disables specific rules only for certain files or directories.","content":"lint.ignore_only **Optional.** Disables specific rules only for certain files or directories."},{"id":"cli/configuration/configuration::lintignore_only::79","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Type:** mapstringstring **Default:** {}","content":"lint.ignore_only **Type:** mapstringstring **Default:** {}"},{"id":"cli/configuration/configuration::lintignore_only::80","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Key:** Rule name or category **Value:** Array of file paths or directories","content":"lint.ignore_only **Key:** Rule name or category **Value:** Array of file paths or directories"},{"id":"cli/configuration/configuration::deps::81","title":"EasyP Configuration Reference","section":"deps","path":"/docs/guide/cli/configuration/configuration#deps","headings":["deps"],"excerpt":"deps **Optional.** Lists external proto dependencies to download and manage.","content":"deps **Optional.** Lists external proto dependencies to download and manage."},{"id":"cli/configuration/configuration::deps::82","title":"EasyP Configuration Reference","section":"deps","path":"/docs/guide/cli/configuration/configuration#deps","headings":["deps"],"excerpt":"deps **Type:** []string **Default:** []","content":"deps **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::dependency-format::83","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format Dependencies follow the format: $GIT_LINK@$VERSION","content":"Dependency Format Dependencies follow the format: $GIT_LINK@$VERSION"},{"id":"cli/configuration/configuration::dependency-format::84","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Components:** $GIT_LINK - Git repository URL (GitHub, GitLab, etc.) $VERSION - Git tag or full commit hash (optional)","content":"Dependency Format **Components:** $GIT_LINK - Git repository URL (GitHub, GitLab, etc.) $VERSION - Git tag or full commit hash (optional)"},{"id":"cli/configuration/configuration::dependency-format::85","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Format variations:** owner/repo - Latest commit from default branch owner/repo@v1.0.0 - Specific git tag owner/repo@47b927cbb41c4fdea1292baf - Full commit hash github.com/owner/repo@version - Full URL","content":"Dependency Format **Format variations:** owner/repo - Latest commit from default branch owner/repo@v1.0.0 - Specific git tag owner/repo@47b927cbb41c4fdea1292baf - Full commit hash github.com/owner/repo@version - Full URL with version gitlab.com/group/repo@tag - GitLab repository"},{"id":"cli/configuration/configuration::dependency-format::86","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Note:** If @$VERSION is omitted, EasyP downloads the latest commit from the repository's default branch.","content":"Dependency Format **Note:** If @$VERSION is omitted, EasyP downloads the latest commit from the repository's default branch."},{"id":"cli/configuration/configuration::generate::87","title":"EasyP Configuration Reference","section":"generate","path":"/docs/guide/cli/configuration/configuration#generate","headings":["generate"],"excerpt":"generate **Optional.** Configures code generation from proto files.","content":"generate **Optional.** Configures code generation from proto files."},{"id":"cli/configuration/configuration::generate::88","title":"EasyP Configuration Reference","section":"generate","path":"/docs/guide/cli/configuration/configuration#generate","headings":["generate"],"excerpt":"generate **Type:** object **Default:** {}","content":"generate **Type:** object **Default:** {}"},{"id":"cli/configuration/configuration::generateinputs::89","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Required when generate is set.** Specifies sources of proto files for generation.","content":"generate.inputs **Required when generate is set.** Specifies sources of proto files for generation."},{"id":"cli/configuration/configuration::generateinputs::90","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Type:** []object (minimum 1 item) **Default:** not set","content":"generate.inputs **Type:** []object (minimum 1 item) **Default:** not set"},{"id":"cli/configuration/configuration::generateinputs::91","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs ```yaml generate: inputs: # Local directory - directory: \"proto\"","content":"generate.inputs ```yaml generate: inputs: # Local directory - directory: \"proto\""},{"id":"cli/configuration/configuration::generateinputs::92","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs Local directory with advanced options - directory: path: \"api/proto\" root: \".\"","content":"generate.inputs Local directory with advanced options - directory: path: \"api/proto\" root: \".\""},{"id":"cli/configuration/configuration::generateinputs::93","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs Remote git repository - git_repo: url: \"github.com/acme/common@v1.0.0\" sub_directory: \"proto\" root: \".\" ```","content":"generate.inputs Remote git repository - git_repo: url: \"github.com/acme/common@v1.0.0\" sub_directory: \"proto\" root: \".\" ```"},{"id":"cli/configuration/configuration::generateinputs::94","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Directory input fields:** directory (string or object) - Local directory path directory.path (string) - Directory path directory.root (string) - Root path for import resolution (default: \".\")","content":"generate.inputs **Directory input fields:** directory (string or object) - Local directory path directory.path (string) - Directory path directory.root (string) - Root path for import resolution (default: \".\")"},{"id":"cli/configuration/configuration::generateinputs::95","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Git repository input fields:** git_repo.url (string) - Repository URL with optional version git_repo.sub_directory (string) - Subdirectory within the repository git_repo.root (string) - Root path used f","content":"generate.inputs **Git repository input fields:** git_repo.url (string) - Repository URL with optional version git_repo.sub_directory (string) - Subdirectory within the repository git_repo.root (string) - Root path used for import resolution"},{"id":"cli/configuration/configuration::generateplugins::96","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Required when generate is set.** Configures protoc plugins for code generation.","content":"generate.plugins **Required when generate is set.** Configures protoc plugins for code generation."},{"id":"cli/configuration/configuration::generateplugins::97","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Type:** []object (minimum 1 item) **Default:** not set","content":"generate.plugins **Type:** []object (minimum 1 item) **Default:** not set"},{"id":"cli/configuration/configuration::generateplugins::98","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins ```yaml generate: plugins: # Local plugin - name: go out: . opts: paths: source_relative","content":"generate.plugins ```yaml generate: plugins: # Local plugin - name: go out: . opts: paths: source_relative"},{"id":"cli/configuration/configuration::generateplugins::99","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Remote plugin - remote: \"buf.build/bufbuild/protovalidate-go:v0.4.0\" out: gen/go opts: paths: source_relative","content":"generate.plugins Remote plugin - remote: \"buf.build/bufbuild/protovalidate-go:v0.4.0\" out: gen/go opts: paths: source_relative"},{"id":"cli/configuration/configuration::generateplugins::100","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Plugin with import dependencies - name: grpc-gateway out: . with_imports: true opts: paths: source_relative ```","content":"generate.plugins Plugin with import dependencies - name: grpc-gateway out: . with_imports: true opts: paths: source_relative ```"},{"id":"cli/configuration/configuration::generateplugins::101","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Plugin fields:** name (string, optional) - Plugin name (omit protoc-gen- prefix) remote (string, optional) - Remote plugin URL for execution path (string, optional) - Path to plugin executable file com","content":"generate.plugins **Plugin fields:** name (string, optional) - Plugin name (omit protoc-gen- prefix) remote (string, optional) - Remote plugin URL for execution path (string, optional) - Path to plugin executable file command ([]string, optional) - Command to execute plugin out (string, optional) - Output directory for generated files; defaults to the resolved generate root opts (mapstring, optional) - Plugin-specific options; each key can be a single scalar value or an array of scalar values with_imports (boolean, optional) - Include imported dependencies"},{"id":"cli/configuration/configuration::generateplugins::102","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Plugin source is one-of: exactly one of name, remote, path, or command must be set.","content":"generate.plugins Plugin source is one-of: exactly one of name, remote, path, or command must be set."},{"id":"cli/configuration/configuration::generateplugins::103","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Common plugin options:** ```yaml Go plugin options opts: paths: source_relative # Generate files relative to input module: github.com/acme/api # Go module path","content":"generate.plugins **Common plugin options:** ```yaml Go plugin options opts: paths: source_relative # Generate files relative to input module: github.com/acme/api # Go module path"},{"id":"cli/configuration/configuration::generateplugins::104","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins gRPC Gateway options opts: paths: source_relative grpc_api_configuration: api.yaml # gRPC API configuration","content":"generate.plugins gRPC Gateway options opts: paths: source_relative grpc_api_configuration: api.yaml # gRPC API configuration"},{"id":"cli/configuration/configuration::generateplugins::105","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins OpenAPI v2 options opts: simple_operation_ids: true # Use simple operation IDs generate_unbound_methods: false # Skip unbound methods","content":"generate.plugins OpenAPI v2 options opts: simple_operation_ids: true # Use simple operation IDs generate_unbound_methods: false # Skip unbound methods"},{"id":"cli/configuration/configuration::generateplugins::106","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins ts-proto options with repeated key values opts: env: node outputServices: - grpc-js - generic-definitions ```","content":"generate.plugins ts-proto options with repeated key values opts: env: node outputServices: - grpc-js - generic-definitions ```"},{"id":"cli/configuration/configuration::generateplugins::107","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins When an opts value is a list, EasyP serializes it as repeated plugin params, e.g. outputServices=grpc-js,outputServices=generic-definitions.","content":"generate.plugins When an opts value is a list, EasyP serializes it as repeated plugin params, e.g. outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/configuration/configuration::breaking::108","title":"EasyP Configuration Reference","section":"breaking","path":"/docs/guide/cli/configuration/configuration#breaking","headings":["breaking"],"excerpt":"breaking **Optional.** Configures backward compatibility checking.","content":"breaking **Optional.** Configures backward compatibility checking."},{"id":"cli/configuration/configuration::breaking::109","title":"EasyP Configuration Reference","section":"breaking","path":"/docs/guide/cli/configuration/configuration#breaking","headings":["breaking"],"excerpt":"breaking **Type:** object **Default:** {}","content":"breaking **Type:** object **Default:** {}"},{"id":"cli/configuration/configuration::breakingignore::110","title":"EasyP Configuration Reference","section":"breaking.ignore","path":"/docs/guide/cli/configuration/configuration#breakingignore","headings":["breaking.ignore"],"excerpt":"breaking.ignore **Optional.** Directories or files to exclude from breaking change detection.","content":"breaking.ignore **Optional.** Directories or files to exclude from breaking change detection."},{"id":"cli/configuration/configuration::breakingignore::111","title":"EasyP Configuration Reference","section":"breaking.ignore","path":"/docs/guide/cli/configuration/configuration#breakingignore","headings":["breaking.ignore"],"excerpt":"breaking.ignore **Type:** []string **Default:** []","content":"breaking.ignore **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::breakingagainst_git_ref::112","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref **Optional.** Git reference (branch, tag, or commit) to compare against for breaking changes.","content":"breaking.against_git_ref **Optional.** Git reference (branch, tag, or commit) to compare against for breaking changes."},{"id":"cli/configuration/configuration::breakingagainst_git_ref::113","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref **Type:** string **Default:** \"\" (falls back to CLI --against default: master)","content":"breaking.against_git_ref **Type:** string **Default:** \"\" (falls back to CLI --against default: master)"},{"id":"cli/configuration/configuration::breakingagainst_git_ref::114","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref Can be overridden by the --against CLI flag.","content":"breaking.against_git_ref Can be overridden by the --against CLI flag."},{"id":"cli/configuration/configuration::configuration-validation::115","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation EasyP validates configuration files on startup and provides helpful error messages:","content":"Configuration Validation EasyP validates configuration files on startup and provides helpful error messages:"},{"id":"cli/configuration/configuration::configuration-validation::116","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation ```bash Invalid rule name Error: invalid rule: INVALID_RULE_NAME","content":"Configuration Validation ```bash Invalid rule name Error: invalid rule: INVALID_RULE_NAME"},{"id":"cli/configuration/configuration::configuration-validation::117","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Missing required field in generate section Error: required field \"plugins\" is missing (path: generate.plugins)","content":"Configuration Validation Missing required field in generate section Error: required field \"plugins\" is missing (path: generate.plugins)"},{"id":"cli/configuration/configuration::configuration-validation::118","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Invalid dependency format Error: invalid dependency format: invalid-repo-url ```","content":"Configuration Validation Invalid dependency format Error: invalid dependency format: invalid-repo-url ```"},{"id":"cli/configuration/configuration::configuration-validation::119","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Use easyp --debug for detailed validation information.","content":"Configuration Validation Use easyp --debug for detailed validation information."},{"id":"cli/configuration/configuration::migration-from-buf::120","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf EasyP is fully compatible with Buf configurations. To migrate:","content":"Migration from Buf EasyP is fully compatible with Buf configurations. To migrate:"},{"id":"cli/configuration/configuration::migration-from-buf::121","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf Place buf.yaml or buf.yml in the project root Run easyp init and confirm migration when prompted Update deps format if using BSR modules Review migrated lint/breaking settings and adjust as needed","content":"Migration from Buf Place buf.yaml or buf.yml in the project root Run easyp init and confirm migration when prompted Update deps format if using BSR modules Review migrated lint/breaking settings and adjust as needed"},{"id":"cli/configuration/configuration::migration-from-buf::122","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf Most Buf configurations work without changes in EasyP.","content":"Migration from Buf Most Buf configurations work without changes in EasyP."},{"id":"cli/generator/examples/go::installing-plugins::0","title":"Go","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/go#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins First, install the necessary plugins for working with gRPC:","content":"Installing Plugins First, install the necessary plugins for working with gRPC:"},{"id":"cli/generator/examples/go::installing-plugins::1","title":"Go","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/go#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc plugins for use with EasyP.","content":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc plugins for use with EasyP."},{"id":"cli/generator/examples/go::example-proto-service::2","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is an example proto file for an Echo service:","content":"Example Proto Service Here is an example proto file for an Echo service:"},{"id":"cli/generator/examples/go::example-proto-service::3","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::example-proto-service::4","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/go::example-proto-service::5","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::example-proto-service::6","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::example-proto-service::7","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::example-proto-service::8","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; }","content":"Example Proto Service message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::example-proto-service::9","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamRequest { string payload = 1; }","content":"Example Proto Service message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::example-proto-service::10","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```","content":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::configuration-setup::11","title":"Go","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/go#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Create and configure the easyp.yaml configuration file:","content":"Configuration Setup Create and configure the easyp.yaml configuration file:"},{"id":"cli/generator/examples/go::configuration-setup::12","title":"Go","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/go#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup This file specifies that two plugins will be used: go for generating Go code and go-grpc for generating gRPC code, along with their respective options.","content":"Configuration Setup This file specifies that two plugins will be used: go for generating Go code and go-grpc for generating gRPC code, along with their respective options."},{"id":"cli/generator/examples/go::generating-code::13","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate code, use the following command:","content":"Generating Code To generate code, use the following command:"},{"id":"cli/generator/examples/go::generating-code::14","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/go::generating-code::15","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go code, which you can interact with directly.","content":"Generating Code Now you have the generated Go code, which you can interact with directly."},{"id":"cli/generator/examples/grpc-gateway::installing-plugins::0","title":"gRPC-Gateway","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/grpc-gateway#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins In addition to the plugins for working with gRPC, you also need to install the following plugins for gRPC-Gateway:","content":"Installing Plugins In addition to the plugins for working with gRPC, you also need to install the following plugins for gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::installing-plugins::1","title":"gRPC-Gateway","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/grpc-gateway#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2, and protoc-gen-grpc-gateway plugins for use with EasyP`.","content":"Installing Plugins These commands will install the protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2, and protoc-gen-grpc-gateway plugins for use with EasyP`."},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::2","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is the initial proto file for an Echo service:","content":"Example Proto Service Here is the initial proto file for an Echo service:"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::3","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::4","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::5","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::6","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::7","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::8","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; } ```","content":"Example Proto Service message EchoResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::9","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service To use gRPC-Gateway, update the proto file to include HTTP options:","content":"Example Proto Service To use gRPC-Gateway, update the proto file to include HTTP options:"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::10","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Example Proto Service ```proto syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::11","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::12","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::13","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::14","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::15","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; } ```","content":"Example Proto Service message EchoResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::16","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Update your easyp.yaml configuration file to include the necessary dependencies and plugins:","content":"Configuration Setup Update your easyp.yaml configuration file to include the necessary dependencies and plugins:"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::17","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup ```yaml deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Configuration Setup ```yaml deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::18","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: grpc-gateway # [!code ++] out: . # [!","content":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: grpc-gateway # [!code ++] out: . # [!code ++] opts: # [!code ++] paths: source_relative # [!code ++] - name: openapiv2 # [!code ++] out: . # [!code ++] opts: # [!code ++] simple_operation_ids: false # [!code ++] generate_unbound_methods: false # [!code ++] ```"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::19","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup The deps section lists dependencies required for proto file imports. In this case, we add github.com/googleapis/googleapis because it contains the annotations.proto file used in the proto service defi","content":"Configuration Setup The deps section lists dependencies required for proto file imports. In this case, we add github.com/googleapis/googleapis because it contains the annotations.proto file used in the proto service definition."},{"id":"cli/generator/examples/grpc-gateway::updating-dependencies::20","title":"gRPC-Gateway","section":"Updating Dependencies","path":"/docs/guide/cli/generator/examples/grpc-gateway#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies After updating your configuration file, run the following command to download the specified dependencies:","content":"Updating Dependencies After updating your configuration file, run the following command to download the specified dependencies:"},{"id":"cli/generator/examples/grpc-gateway::updating-dependencies::21","title":"gRPC-Gateway","section":"Updating Dependencies","path":"/docs/guide/cli/generator/examples/grpc-gateway#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies For more details on managing dependencies, refer to the Package Manager section.","content":"Updating Dependencies For more details on managing dependencies, refer to the Package Manager section."},{"id":"cli/generator/examples/grpc-gateway::generating-code::22","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate the code, use the following command:","content":"Generating Code To generate the code, use the following command:"},{"id":"cli/generator/examples/grpc-gateway::generating-code::23","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/grpc-gateway::generating-code::24","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go and gRPC-Gateway code, which you can interact with directly.","content":"Generating Code Now you have the generated Go and gRPC-Gateway code, which you can interact with directly."},{"id":"cli/generator/examples/validate::installing-plugins::0","title":"Validate","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/validate#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins First, install the necessary plugins for working with gRPC:","content":"Installing Plugins First, install the necessary plugins for working with gRPC:"},{"id":"cli/generator/examples/validate::installing-plugins::1","title":"Validate","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/validate#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc and protoc-gen-validate plugins for use with EasyP.","content":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc and protoc-gen-validate plugins for use with EasyP."},{"id":"cli/generator/examples/validate::example-proto-service::2","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is an example proto file for an Echo service:","content":"Example Proto Service Here is an example proto file for an Echo service:"},{"id":"cli/generator/examples/validate::example-proto-service::3","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::example-proto-service::4","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/validate::example-proto-service::5","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service import \"validate/validate.proto\";","content":"Example Proto Service import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::example-proto-service::6","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::example-proto-service::7","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::example-proto-service::8","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Example Proto Service message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::example-proto-service::9","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; }","content":"Example Proto Service message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::example-proto-service::10","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Example Proto Service message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::example-proto-service::11","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```","content":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::configuration-setup::12","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Create and configure the easyp.yaml configuration file:","content":"Configuration Setup Create and configure the easyp.yaml configuration file:"},{"id":"cli/generator/examples/validate::configuration-setup::13","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Configuration Setup ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::configuration-setup::14","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: validate out: . opts: paths: source_r","content":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: validate out: . opts: paths: source_relative lang: \"go\" ```"},{"id":"cli/generator/examples/validate::generating-code::15","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate code, use the following command:","content":"Generating Code To generate code, use the following command:"},{"id":"cli/generator/examples/validate::generating-code::16","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/validate::generating-code::17","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go code, which you can interact with directly.","content":"Generating Code Now you have the generated Go code, which you can interact with directly."},{"id":"cli/generator/generator::top::0","title":"Generator","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP includes a powerful generator that simplifies the process of generating code from proto files. By using YAML configurations, EasyP makes this process more user-friendly and intuitive compared to using the protoc co","content":"EasyP includes a powerful generator that simplifies the process of generating code from proto files. By using YAML configurations, EasyP makes this process more user-friendly and intuitive compared to using the protoc command directly."},{"id":"cli/generator/generator::key-features-of-the-generator::1","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Simplified Code Generation**: - Generate code from proto files using a YAML configuration. - Avoid the need to write long and complex protoc commands.","content":"Key Features of the Generator **Simplified Code Generation**: - Generate code from proto files using a YAML configuration. - Avoid the need to write long and complex protoc commands."},{"id":"cli/generator/generator::key-features-of-the-generator::2","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Wrapper around protoc**: - EasyP functions as a wrapper around protoc, providing a more convenient API through configuration files. - Supports all options and plugins available in protoc.","content":"Key Features of the Generator **Wrapper around protoc**: - EasyP functions as a wrapper around protoc, providing a more convenient API through configuration files. - Supports all options and plugins available in protoc."},{"id":"cli/generator/generator::key-features-of-the-generator::3","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Flexibility and Customization**: - Use the same parameters as protoc plugins, directly in the configuration file. - Support for multiple plugins and their parameters in a single configurat","content":"Key Features of the Generator **Flexibility and Customization**: - Use the same parameters as protoc plugins, directly in the configuration file. - Support for multiple plugins and their parameters in a single configuration."},{"id":"cli/generator/generator::key-features-of-the-generator::4","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Generate Code from Multiple Sources**: - Generate code from local directories or remote repositories. - Easily integrate with existing projects and repositories.","content":"Key Features of the Generator **Generate Code from Multiple Sources**: - Generate code from local directories or remote repositories. - Easily integrate with existing projects and repositories."},{"id":"cli/generator/generator::key-features-of-the-generator::5","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Remote Generation**: - Generate code from remote Git repositories without local checkout.","content":"Key Features of the Generator **Remote Generation**: - Generate code from remote Git repositories without local checkout."},{"id":"cli/generator/generator::key-features-of-the-generator::6","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Package Manager Integration**: - Seamless integration with EasyP's package manager for dependency management. - Automatic resolution and inclusion of proto dependencies.","content":"Key Features of the Generator **Package Manager Integration**: - Seamless integration with EasyP's package manager for dependency management. - Automatic resolution and inclusion of proto dependencies."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example ```yaml Package manager dependencies deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 - github.com/bufbuild/protoc-gen-validate@","content":"Complete Configuration Example ```yaml Package manager dependencies deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::complete-configuration-example::8","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Code generation configuration generate: inputs: # Local directory input - directory: path: \"proto\" root: \".\" # Remote Git repository input - git_repo: url: \"github.com/acme/weather@v1.2.3\" ","content":"Complete Configuration Example Code generation configuration generate: inputs: # Local directory input - directory: path: \"proto\" root: \".\" # Remote Git repository input - git_repo: url: \"github.com/acme/weather@v1.2.3\" sub_directory: \"proto/api\" # Another remote repository - git_repo: url: \"https://github.com/company/internal-protos.git\" sub_directory: \"definitions\" plugins: # Local plugin execution - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myproject with_imports: true # Local plugin with custom options - name: go-grpc out: ./gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"cli/generator/generator::complete-configuration-example::9","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - automatically set file and field options managed: enabled: true disable: - module: github.com/googleapis/googleapis # Disable for specific module override: - file_option: go_","content":"Complete Configuration Example Managed mode - automatically set file and field options managed: enabled: true disable: - module: github.com/googleapis/googleapis # Disable for specific module override: - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go - file_option: java_package_prefix value: com.mycompany - file_option: csharp_namespace_prefix value: MyCompany - field_option: jstype value: JS_STRING path: api/v1/ # Apply to specific path"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example ```","content":"Complete Configuration Example ```"},{"id":"cli/generator/generator::local-directory-input::11","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Local directory input is the most common and straightforward way to specify proto files for generation. Use this when your proto files are already present in your project directory structure.","content":"Local Directory Input Local directory input is the most common and straightforward way to specify proto files for generation. Use this when your proto files are already present in your project directory structure."},{"id":"cli/generator/generator::local-directory-input::12","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **When to use:** Proto files are part of your project repository You need full control over proto file organization Working with a single service or application Proto files don't change frequently","content":"Local Directory Input **When to use:** Proto files are part of your project repository You need full control over proto file organization Working with a single service or application Proto files don't change frequently"},{"id":"cli/generator/generator::local-directory-input::13","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input The root parameter is particularly useful in monorepo setups where you need to control import path resolution. When root is set to a parent directory, import paths in your proto files will be resolv","content":"Local Directory Input The root parameter is particularly useful in monorepo setups where you need to control import path resolution. When root is set to a parent directory, import paths in your proto files will be resolved relative to that root, not the current working directory."},{"id":"cli/generator/generator::local-directory-input::14","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **Parameters:**","content":"Local Directory Input **Parameters:**"},{"id":"cli/generator/generator::local-directory-input::15","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- path string ✅ - Path to the directory containing proto files root string ❌ \".\" Root directory used f","content":"Local Directory Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- path string ✅ - Path to the directory containing proto files root string ❌ \".\" Root directory used for import path resolution"},{"id":"cli/generator/generator::local-directory-input::16","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **Examples:**","content":"Local Directory Input **Examples:**"},{"id":"cli/generator/generator::local-directory-input::17","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input These examples show the difference between basic directory specification and advanced configuration with custom import resolution:","content":"Local Directory Input These examples show the difference between basic directory specification and advanced configuration with custom import resolution:"},{"id":"cli/generator/generator::local-directory-input::18","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input ```yaml Basic usage - Simple path specification inputs: - directory: \"api/proto\"","content":"Local Directory Input ```yaml Basic usage - Simple path specification inputs: - directory: \"api/proto\""},{"id":"cli/generator/generator::local-directory-input::19","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Advanced usage with custom root - Controls import path resolution inputs: - directory: path: \"services/auth/proto\" root: \"services/auth\" # Imports will be relative to this path ```","content":"Local Directory Input Advanced usage with custom root - Controls import path resolution inputs: - directory: path: \"services/auth/proto\" root: \"services/auth\" # Imports will be relative to this path ```"},{"id":"cli/generator/generator::remote-git-repository-input::20","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Remote Git repository input allows you to generate code from proto files hosted in external repositories without requiring a local checkout. This is particularly powerful for consuming APIs fr","content":"Remote Git Repository Input Remote Git repository input allows you to generate code from proto files hosted in external repositories without requiring a local checkout. This is particularly powerful for consuming APIs from other teams or external vendors."},{"id":"cli/generator/generator::remote-git-repository-input::21","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **When to use:** Consuming proto definitions from other teams or services Integrating with vendor APIs that provide proto definitions Working with shared proto libraries across multiple projec","content":"Remote Git Repository Input **When to use:** Consuming proto definitions from other teams or services Integrating with vendor APIs that provide proto definitions Working with shared proto libraries across multiple projects You want to ensure you're always using the correct version of external APIs"},{"id":"cli/generator/generator::remote-git-repository-input::22","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Recommended approach:** Always pin to specific versions in production (@v1.0.0, not latest) Use semantic versions when available for easier dependency management Prefer public tags over comm","content":"Remote Git Repository Input **Recommended approach:** Always pin to specific versions in production (@v1.0.0, not latest) Use semantic versions when available for easier dependency management Prefer public tags over commit hashes for better traceability"},{"id":"cli/generator/generator::remote-git-repository-input::23","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input The root parameter controls import resolution root for files from this repository.","content":"Remote Git Repository Input The root parameter controls import resolution root for files from this repository."},{"id":"cli/generator/generator::remote-git-repository-input::24","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Parameters:**","content":"Remote Git Repository Input **Parameters:**"},{"id":"cli/generator/generator::remote-git-repository-input::25","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- url string ✅ - Git repository URL with optional version/tag/commit sub_directory string ❌ \"\" S","content":"Remote Git Repository Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- url string ✅ - Git repository URL with optional version/tag/commit sub_directory string ❌ \"\" Subdirectory within the repository containing proto files root string ❌ \"\" Root path used for import resolution"},{"id":"cli/generator/generator::remote-git-repository-input::26","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **URL Format Options:**","content":"Remote Git Repository Input **URL Format Options:**"},{"id":"cli/generator/generator::remote-git-repository-input::27","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input EasyP supports multiple URL formats to give you flexibility in how you reference remote repositories. Each format serves different use cases depending on your stability and versioning requirem","content":"Remote Git Repository Input EasyP supports multiple URL formats to give you flexibility in how you reference remote repositories. Each format serves different use cases depending on your stability and versioning requirements:"},{"id":"cli/generator/generator::remote-git-repository-input::28","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Tagged versions** are recommended for production as they provide stable, immutable references **Semantic versions** offer better readability and dependency management **Commit hashes** give ","content":"Remote Git Repository Input **Tagged versions** are recommended for production as they provide stable, immutable references **Semantic versions** offer better readability and dependency management **Commit hashes** give you access to specific commits when tags aren't available **Latest** should only be used in development environments due to unpredictability **Full HTTPS URLs** are useful for private repositories or non-GitHub hosting"},{"id":"cli/generator/generator::remote-git-repository-input::29","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input ```yaml Tag version - Best for production stability url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Remote Git Repository Input ```yaml Tag version - Best for production stability url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::remote-git-repository-input::30","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Semantic version - Easier dependency management url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Remote Git Repository Input Semantic version - Easier dependency management url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::remote-git-repository-input::31","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Commit hash - When you need a specific commit url: \"github.com/company/protos@abc123def456\"","content":"Remote Git Repository Input Commit hash - When you need a specific commit url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::remote-git-repository-input::32","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Latest - Development only, not recommended for production url: \"github.com/company/protos\"","content":"Remote Git Repository Input Latest - Development only, not recommended for production url: \"github.com/company/protos\""},{"id":"cli/generator/generator::remote-git-repository-input::33","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Full HTTPS URL - For private repos or custom Git hosts url: \"https://github.com/company/private-protos.git\" ```","content":"Remote Git Repository Input Full HTTPS URL - For private repos or custom Git hosts url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::remote-git-repository-input::34","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Examples:**","content":"Remote Git Repository Input **Examples:**"},{"id":"cli/generator/generator::remote-git-repository-input::35","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input These examples demonstrate common patterns for consuming remote proto definitions from different types of repositories:","content":"Remote Git Repository Input These examples demonstrate common patterns for consuming remote proto definitions from different types of repositories:"},{"id":"cli/generator/generator::plugin-configuration::36","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration Plugin configuration is where you specify which code generators to run and how they should behave. EasyP supports any protoc plugin, making it extremely flexible for different language ecosystems and","content":"Plugin Configuration Plugin configuration is where you specify which code generators to run and how they should behave. EasyP supports any protoc plugin, making it extremely flexible for different language ecosystems and use cases."},{"id":"cli/generator/generator::plugin-configuration::37","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration At a high level, there are **four ways to specify how a plugin should be executed**:","content":"Plugin Configuration At a high level, there are **four ways to specify how a plugin should be executed**:"},{"id":"cli/generator/generator::plugin-configuration::38","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration **name** – run plugin by name from PATH or use a builtin plugin. **path** – run plugin by absolute/relative path to an executable file. **remote** – run plugin via remote URL (EasyP remote executor).","content":"Plugin Configuration **name** – run plugin by name from PATH or use a builtin plugin. **path** – run plugin by absolute/relative path to an executable file. **remote** – run plugin via remote URL (EasyP remote executor). **command** – run plugin via arbitrary command (for example, go run ...)."},{"id":"cli/generator/generator::plugin-configuration::39","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration Only **one** of name, path, remote, or command must be specified for each plugin.","content":"Plugin Configuration Only **one** of name, path, remote, or command must be specified for each plugin."},{"id":"cli/generator/generator::plugin-by-name-name::40","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) Local plugin execution by name is the standard approach where plugins are installed on your system and executed directly by EasyP.","content":"Plugin by Name (name) Local plugin execution by name is the standard approach where plugins are installed on your system and executed directly by EasyP."},{"id":"cli/generator/generator::plugin-by-name-name::41","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) **When to use name:** Standard language support (Go, Python, TypeScript, etc.) You have control over the build environment Performance is critical (no network overhead) You want to rely on PATH or b","content":"Plugin by Name (name) **When to use name:** Standard language support (Go, Python, TypeScript, etc.) You have control over the build environment Performance is critical (no network overhead) You want to rely on PATH or builtin plugins"},{"id":"cli/generator/generator::plugin-by-name-name::42","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) **Installation requirements:** Plugins must be installed and available in your PATH (if not using builtin plugins). Plugin names follow the protoc-gen-{name} convention. Use package managers (go ins","content":"Plugin by Name (name) **Installation requirements:** Plugins must be installed and available in your PATH (if not using builtin plugins). Plugin names follow the protoc-gen-{name} convention. Use package managers (go install, npm install, pip install) for installation."},{"id":"cli/generator/generator::plugin-by-name-name::43","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) The with_imports parameter is crucial when you're using dependencies from the package manager. Set it to true to include proto files from your deps section in the generation process.","content":"Plugin by Name (name) The with_imports parameter is crucial when you're using dependencies from the package manager. Set it to true to include proto files from your deps section in the generation process."},{"id":"cli/generator/generator::plugin-by-path-path::44","title":"Generator","section":"Plugin by Path (path)","path":"/docs/guide/cli/generator/generator#plugin-by-path-path","headings":["Plugin by Path (path)"],"excerpt":"Plugin by Path (path) Sometimes you need to run a plugin from a specific binary without putting it into PATH (for example, a binary in your repo or in a build directory). In this case you can specify an explicit path:","content":"Plugin by Path (path) Sometimes you need to run a plugin from a specific binary without putting it into PATH (for example, a binary in your repo or in a build directory). In this case you can specify an explicit path:"},{"id":"cli/generator/generator::plugin-by-path-path::45","title":"Generator","section":"Plugin by Path (path)","path":"/docs/guide/cli/generator/generator#plugin-by-path-path","headings":["Plugin by Path (path)"],"excerpt":"Plugin by Path (path) **When to use path:** You keep plugin binaries in the repository (for reproducible builds). You use different plugin versions side-by-side. You don't want to pollute the global PATH.","content":"Plugin by Path (path) **When to use path:** You keep plugin binaries in the repository (for reproducible builds). You use different plugin versions side-by-side. You don't want to pollute the global PATH."},{"id":"cli/generator/generator::remote-plugin-remote::46","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) Remote plugins are executed via a remote URL. EasyP will send a CodeGeneratorRequest to the remote endpoint and receive a CodeGeneratorResponse back.","content":"Remote Plugin (remote) Remote plugins are executed via a remote URL. EasyP will send a CodeGeneratorRequest to the remote endpoint and receive a CodeGeneratorResponse back."},{"id":"cli/generator/generator::remote-plugin-remote::47","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) Below is a real example of using the EasyP API Service as a remote plugin executor (same format as in the API Service docs):","content":"Remote Plugin (remote) Below is a real example of using the EasyP API Service as a remote plugin executor (same format as in the API Service docs):"},{"id":"cli/generator/generator::remote-plugin-remote::48","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) ```yaml generate: plugins: # Remote plugin execution via EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Remote Plugin (remote) ```yaml generate: plugins: # Remote plugin execution via EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote-plugin-remote::49","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Remote Plugin (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote-plugin-remote::50","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) **Typical use cases for remote:** Centralized plugin service inside your organization (e.g. EasyP API Service). Running heavy plugins on a dedicated server instead of CI agents. Sharing the same pl","content":"Remote Plugin (remote) **Typical use cases for remote:** Centralized plugin service inside your organization (e.g. EasyP API Service). Running heavy plugins on a dedicated server instead of CI agents. Sharing the same plugin implementation across multiple teams."},{"id":"cli/generator/generator::executing-plugin-via-command-command::51","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) You can specify a plugin as an array of commands to execute. This is useful for running plugins via go run or any other tool without prior installation of the plugin binary:","content":"Executing Plugin via Command (command) You can specify a plugin as an array of commands to execute. This is useful for running plugins via go run or any other tool without prior installation of the plugin binary:"},{"id":"cli/generator/generator::executing-plugin-via-command-command::52","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command)","content":"Executing Plugin via Command (command)"},{"id":"cli/generator/generator::executing-plugin-via-command-command::53","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) In this mode EasyP: **builds and runs the command** you provide as a child process; **writes CodeGeneratorRequest to stdin** of the process; **reads CodeGeneratorResponse from stdou","content":"Executing Plugin via Command (command) In this mode EasyP: **builds and runs the command** you provide as a child process; **writes CodeGeneratorRequest to stdin** of the process; **reads CodeGeneratorResponse from stdout**, just like with regular protoc plugins."},{"id":"cli/generator/generator::executing-plugin-via-command-command::54","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Plugin Source Priority:** command — execute via specified command (highest priority) remote — remote plugin via URL name — local plugin from PATH or builtin plugin path — path to ","content":"Executing Plugin via Command (command) **Plugin Source Priority:** command — execute via specified command (highest priority) remote — remote plugin via URL name — local plugin from PATH or builtin plugin path — path to plugin executable file"},{"id":"cli/generator/generator::executing-plugin-via-command-command::55","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Parameters (plugin sources and common options):**","content":"Executing Plugin via Command (command) **Parameters (plugin sources and common options):**"},{"id":"cli/generator/generator::executing-plugin-via-command-command::56","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- name string ❌ - Plugin name or identifier (e.g. go, go-grpc, grpc-gateway) command ","content":"Executing Plugin via Command (command) Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- name string ❌ - Plugin name or identifier (e.g. go, go-grpc, grpc-gateway) command []string ❌ - Command to execute plugin (e.g., [\"go\", \"run\", \"package\"]) remote string ❌ - Remote plugin URL path string ❌ - Path to plugin executable file out string ❌ resolved generate root Output directory for generated files opts mapstring ❌ {} Plugin-specific options; list values are emitted as repeated key=value params with_imports bool ❌ false Include proto files from dependencies"},{"id":"cli/generator/generator::executing-plugin-via-command-command::57","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Note:** Only one plugin source (name, command, remote, or path) must be specified for each plugin. If opts.outputServices is set to [\"grpc-js\", \"generic-definitions\"], EasyP sends","content":"Executing Plugin via Command (command) **Note:** Only one plugin source (name, command, remote, or path) must be specified for each plugin. If opts.outputServices is set to [\"grpc-js\", \"generic-definitions\"], EasyP sends outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::executing-plugin-via-command-command::58","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Command source examples:**","content":"Executing Plugin via Command (command) **Command source examples:**"},{"id":"cli/generator/generator::executing-plugin-via-command-command::59","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Executing Plugin via Command (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::executing-plugin-via-command-command::60","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) plugins: # 1) gRPC-Gateway via go run (no pre-installed binary required) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.25.1\"] out: .","content":"Executing Plugin via Command (command) plugins: # 1) gRPC-Gateway via go run (no pre-installed binary required) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.25.1\"] out: ./gen/go opts: paths: source_relative generate_unbound_methods: true"},{"id":"cli/generator/generator::executing-plugin-via-command-command::61","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) 2) protoc-gen-validate via go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Executing Plugin via Command (command) 2) protoc-gen-validate via go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go"},{"id":"cli/generator/generator::executing-plugin-via-command-command::62","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) 3) Any custom wrapper script - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Executing Plugin via Command (command) 3) Any custom wrapper script - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::63","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins EasyP includes builtin plugins for basic protobuf and gRPC languages. These plugins are embedded in the binary as WASM modules and do not require installation of external dependencies.","content":"Builtin Plugins EasyP includes builtin plugins for basic protobuf and gRPC languages. These plugins are embedded in the binary as WASM modules and do not require installation of external dependencies."},{"id":"cli/generator/generator::builtin-plugins::64","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins **Benefits of builtin plugins:** **Portability**: Single binary with all necessary plugins **Convenience**: No need to install external dependencies **Stability**: Plugin versions are fixed in the binary ","content":"Builtin Plugins **Benefits of builtin plugins:** **Portability**: Single binary with all necessary plugins **Convenience**: No need to install external dependencies **Stability**: Plugin versions are fixed in the binary **Isolation**: Independent of system plugin installations"},{"id":"cli/generator/generator::builtin-plugins::65","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins **Supported builtin plugins:**","content":"Builtin Plugins **Supported builtin plugins:**"},{"id":"cli/generator/generator::protobuf-base-plugins::66","title":"Generator","section":"Protobuf Base Plugins","path":"/docs/guide/cli/generator/generator#protobuf-base-plugins","headings":["Protobuf Base Plugins"],"excerpt":"Protobuf Base Plugins The following plugins are builtin for generating base protobuf code:","content":"Protobuf Base Plugins The following plugins are builtin for generating base protobuf code:"},{"id":"cli/generator/generator::protobuf-base-plugins::67","title":"Generator","section":"Protobuf Base Plugins","path":"/docs/guide/cli/generator/generator#protobuf-base-plugins","headings":["Protobuf Base Plugins"],"excerpt":"Protobuf Base Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- cpp Generate C++ code from proto files protoc-gen-cpp csharp Generate C# code from proto ","content":"Protobuf Base Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- cpp Generate C++ code from proto files protoc-gen-cpp csharp Generate C# code from proto files protoc-gen-csharp java Generate Java code from proto files protoc-gen-java kotlin Generate Kotlin code from proto files protoc-gen-kotlin objc Generate Objective-C code from proto files protoc-gen-objc php Generate PHP code from proto files protoc-gen-php python Generate Python code from proto files protoc-gen-python ruby Generate Ruby code from proto files protoc-gen-ruby"},{"id":"cli/generator/generator::grpc-plugins::68","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins The following plugins are builtin for generating gRPC code:","content":"gRPC Plugins The following plugins are builtin for generating gRPC code:"},{"id":"cli/generator/generator::grpc-plugins::69","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- grpc_cpp Generate gRPC code for C++ grpc_cpp_plugin grpc_csharp Generate gRPC code for C# grpc_csh","content":"gRPC Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- grpc_cpp Generate gRPC code for C++ grpc_cpp_plugin grpc_csharp Generate gRPC code for C# grpc_csharp_plugin grpc_java Generate gRPC code for Java grpc_java_plugin grpc_node Generate gRPC code for Node.js grpc_node_plugin grpc_objc Generate gRPC code for Objective-C grpc_objective_c_plugin grpc_php Generate gRPC code for PHP grpc_php_plugin grpc_python Generate gRPC code for Python grpc_python_plugin grpc_ruby Generate gRPC code for Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc-plugins::70","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Plugin Selection Logic:**","content":"gRPC Plugins **Plugin Selection Logic:**"},{"id":"cli/generator/generator::grpc-plugins::71","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins EasyP uses the following priority when selecting an executor for a plugin:","content":"gRPC Plugins EasyP uses the following priority when selecting an executor for a plugin:"},{"id":"cli/generator/generator::grpc-plugins::72","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Remote plugin** (if url is specified) — always has the highest priority **Builtin plugin** (if plugin is builtin and not found in PATH) — used automatically **Local plugin** (from PATH) — used by default f","content":"gRPC Plugins **Remote plugin** (if url is specified) — always has the highest priority **Builtin plugin** (if plugin is builtin and not found in PATH) — used automatically **Local plugin** (from PATH) — used by default for backward compatibility"},{"id":"cli/generator/generator::grpc-plugins::73","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Usage Example:**","content":"gRPC Plugins **Usage Example:**"},{"id":"cli/generator/generator::grpc-plugins::74","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Requirements:**","content":"gRPC Plugins **Requirements:**"},{"id":"cli/generator/generator::grpc-plugins::75","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Builtin plugins are included in the EasyP binary:","content":"gRPC Plugins Builtin plugins are included in the EasyP binary:"},{"id":"cli/generator/generator::grpc-plugins::76","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins ```bash Build go build ./cmd/easyp","content":"gRPC Plugins ```bash Build go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc-plugins::77","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Install go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC Plugins Install go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc-plugins::78","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Backward Compatibility:**","content":"gRPC Plugins **Backward Compatibility:**"},{"id":"cli/generator/generator::grpc-plugins::79","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Builtin plugins are fully compatible with existing configurations. If a plugin is found in PATH, it will be used instead of the builtin one. This ensures that:","content":"gRPC Plugins Builtin plugins are fully compatible with existing configurations. If a plugin is found in PATH, it will be used instead of the builtin one. This ensures that:"},{"id":"cli/generator/generator::grpc-plugins::80","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Existing configurations continue to work without changes You can override a builtin plugin by installing it in your system Priority is given to local installations for flexibility","content":"gRPC Plugins Existing configurations continue to work without changes You can override a builtin plugin by installing it in your system Priority is given to local installations for flexibility"},{"id":"cli/generator/generator::plugin-options-reference::81","title":"Generator","section":"Plugin Options Reference","path":"/docs/guide/cli/generator/generator#plugin-options-reference","headings":["Plugin Options Reference"],"excerpt":"Plugin Options Reference This section covers the most commonly used plugins and their configuration options. Each plugin has specific parameters that control how code is generated, and understanding these options is cruc","content":"Plugin Options Reference This section covers the most commonly used plugins and their configuration options. Each plugin has specific parameters that control how code is generated, and understanding these options is crucial for getting the output you need."},{"id":"cli/generator/generator::go-plugins::82","title":"Generator","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Go plugins are the most mature and widely used protoc plugins. The paths option controls how import paths are resolved, while other options provide fine-grained control over the generated code:","content":"Go Plugins Go plugins are the most mature and widely used protoc plugins. The paths option controls how import paths are resolved, while other options provide fine-grained control over the generated code:"},{"id":"cli/generator/generator::grpc-gateway-plugins::83","title":"Generator","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins gRPC-Gateway plugins enable you to serve gRPC services as REST APIs and generate OpenAPI documentation. These are essential for building HTTP/JSON APIs from gRPC services:","content":"gRPC-Gateway Plugins gRPC-Gateway plugins enable you to serve gRPC services as REST APIs and generate OpenAPI documentation. These are essential for building HTTP/JSON APIs from gRPC services:"},{"id":"cli/generator/generator::validation-plugins::84","title":"Generator","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Validation plugins generate code that automatically validates proto message fields based on constraints defined in your proto files. This eliminates the need for manual validation code:","content":"Validation Plugins Validation plugins generate code that automatically validates proto message fields based on constraints defined in your proto files. This eliminates the need for manual validation code:"},{"id":"cli/generator/generator::typescriptjavascript-plugins::85","title":"Generator","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript plugins are essential for frontend development, providing type-safe interfaces for your proto definitions and gRPC services in web applications:","content":"TypeScript/JavaScript Plugins TypeScript plugins are essential for frontend development, providing type-safe interfaces for your proto definitions and gRPC services in web applications:"},{"id":"cli/generator/generator::managed-mode::86","title":"Generator","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode automatically sets file and field options in your protobuf descriptors during code generation without modifying the original .proto files. This feature is compatible with buf's managed mode and ","content":"Managed Mode Managed mode automatically sets file and field options in your protobuf descriptors during code generation without modifying the original .proto files. This feature is compatible with buf's managed mode and provides a consistent way to manage language-specific options across your codebase."},{"id":"cli/generator/generator::managed-mode::87","title":"Generator","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Key benefits:** **No proto file modifications**: Options are applied at generation time, keeping your proto files clean **Consistent defaults**: Automatic application of language-specific naming convention","content":"Managed Mode **Key benefits:** **No proto file modifications**: Options are applied at generation time, keeping your proto files clean **Consistent defaults**: Automatic application of language-specific naming conventions **Centralized configuration**: Manage all options in one place (easyp.yaml) **Module-specific rules**: Apply different options to different modules or paths **buf compatibility**: Works the same way as buf managed mode"},{"id":"cli/generator/generator::how-it-works::88","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works When managed mode is enabled, EasyP automatically applies file and field options to your protobuf descriptors before code generation. This happens in memory, so your original .proto files remain unchanged.","content":"How It Works When managed mode is enabled, EasyP automatically applies file and field options to your protobuf descriptors before code generation. This happens in memory, so your original .proto files remain unchanged."},{"id":"cli/generator/generator::how-it-works::89","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Default values** are applied for certain options based on language conventions: Java: java_package_prefix defaults to \"com\", java_multiple_files defaults to true C#: csharp_namespace defaults to PascalCase","content":"How It Works **Default values** are applied for certain options based on language conventions: Java: java_package_prefix defaults to \"com\", java_multiple_files defaults to true C#: csharp_namespace defaults to PascalCase of package name Ruby: ruby_package defaults to PascalCase with :: separator PHP: php_namespace defaults to PascalCase with \\ separator Objective-C: objc_class_prefix defaults to first letters of package parts C++: cc_enable_arenas defaults to true"},{"id":"cli/generator/generator::how-it-works::90","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, protobuf package, path, or field. Without module, package, or path, an override applies to all files in the g","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, protobuf package, path, or field. Without module, package, or path, an override applies to all files in the generation request, including dependencies and git_repo inputs."},{"id":"cli/generator/generator::how-it-works::91","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files. This is the recommended way to exclude external dependencies that already define their own options.","content":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files. This is the recommended way to exclude external dependencies that already define their own options."},{"id":"cli/generator/generator::configuration::92","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration ```yaml generate: managed: enabled: true disable: # Disable managed mode for specific module - module: github.com/googleapis/googleapis # Disable specific option globally - file_option: java_package_prefix","content":"Configuration ```yaml generate: managed: enabled: true disable: # Disable managed mode for specific module - module: github.com/googleapis/googleapis # Disable specific option globally - file_option: java_package_prefix"},{"id":"cli/generator/generator::configuration::93","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration Disable for specific protobuf package - package: acme.weather.v1 file_option: java_package # Disable for specific path - path: legacy/ file_option: go_package # Disable field option for specific field - fie","content":"Configuration Disable for specific protobuf package - package: acme.weather.v1 file_option: java_package # Disable for specific path - path: legacy/ file_option: go_package # Disable field option for specific field - field_option: jstype field: com.example.User.id override: # Override go_package_prefix for all files - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go # Override for specific module - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos"},{"id":"cli/generator/generator::configuration::94","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration Override for specific protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Override for specific path - file_option: csharp_namespace_pre","content":"Configuration Override for specific protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Override for specific path - file_option: csharp_namespace_prefix value: MyCompany path: api/v1/ # Override for multiple files with same value using prefix path # This matches both internal/cms/bmi.proto and internal/cms/bmi_service.proto - file_option: go_package value: spec/cms/bmi path: \"internal/cms/bmi\" # Override field option for specific path - field_option: jstype value: JS_STRING path: api/v1/ # Override for specific field - field_option: jstype value: JS_NUMBER field: com.example.User.big_id ```"},{"id":"cli/generator/generator::supported-file-options::95","title":"Generator","section":"Supported File Options","path":"/docs/guide/cli/generator/generator#supported-file-options","headings":["Supported File Options"],"excerpt":"Supported File Options Option Description Has Default? -------- ------------- -------------- go_package Go import path ❌ go_package_prefix Prefix for Go import paths ❌ java_package Java package name ❌ java_package_prefix","content":"Supported File Options Option Description Has Default? -------- ------------- -------------- go_package Go import path ❌ go_package_prefix Prefix for Go import paths ❌ java_package Java package name ❌ java_package_prefix Prefix for Java packages ✅ (\"com\") java_package_suffix Suffix for Java packages ❌ java_multiple_files Generate multiple Java files ✅ (true) java_outer_classname Outer class name ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 validation ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Prefix for C# namespaces ❌ ruby_package Ruby module name ✅ (PascalCase with ::) ruby_package_suffix Suffix for Ruby packages ❌ php_namespace PHP namespace ✅ (PascalCase with \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Suffix for PHP metadata ❌ objc_class_prefix Objective-C class prefix ✅ (First letters) swift_prefix Swift prefix ❌ optimize_for Code generation optimization ❌ cc_enable_arenas C++ arena allocation ✅ (true)"},{"id":"cli/generator/generator::supported-field-options::96","title":"Generator","section":"Supported Field Options","path":"/docs/guide/cli/generator/generator#supported-field-options","headings":["Supported Field Options"],"excerpt":"Supported Field Options Option Description Applies To -------- ------------- ------------ jstype JavaScript type for 64-bit integers int64, uint64, sint64, fixed64, sfixed64","content":"Supported Field Options Option Description Applies To -------- ------------- ------------ jstype JavaScript type for 64-bit integers int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::basic-setup-with-defaults::97","title":"Generator","section":"Basic Setup with Defaults","path":"/docs/guide/cli/generator/generator#basic-setup-with-defaults","headings":["Basic Setup with Defaults"],"excerpt":"Basic Setup with Defaults Enable managed mode to get automatic defaults for all supported languages:","content":"Basic Setup with Defaults Enable managed mode to get automatic defaults for all supported languages:"},{"id":"cli/generator/generator::basic-setup-with-defaults::98","title":"Generator","section":"Basic Setup with Defaults","path":"/docs/guide/cli/generator/generator#basic-setup-with-defaults","headings":["Basic Setup with Defaults"],"excerpt":"Basic Setup with Defaults This will automatically: Set java_package to com. for all files Set java_multiple_files to true Set csharp_namespace to PascalCase of package name Set ruby_package to PascalCase with :: separato","content":"Basic Setup with Defaults This will automatically: Set java_package to com. for all files Set java_multiple_files to true Set csharp_namespace to PascalCase of package name Set ruby_package to PascalCase with :: separator And more..."},{"id":"cli/generator/generator::custom-go-package-prefix::99","title":"Generator","section":"Custom Go Package Prefix","path":"/docs/guide/cli/generator/generator#custom-go-package-prefix","headings":["Custom Go Package Prefix"],"excerpt":"Custom Go Package Prefix Override the Go package prefix for your project:","content":"Custom Go Package Prefix Override the Go package prefix for your project:"},{"id":"cli/generator/generator::custom-go-package-prefix::100","title":"Generator","section":"Custom Go Package Prefix","path":"/docs/guide/cli/generator/generator#custom-go-package-prefix","headings":["Custom Go Package Prefix"],"excerpt":"Custom Go Package Prefix This will set go_package to github.com/mycompany/myproject/gen/go/ for all files.","content":"Custom Go Package Prefix This will set go_package to github.com/mycompany/myproject/gen/go/ for all files."},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::101","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers For more complex path generation, you can use markers in go_package_prefix or go_package values:","content":"Dynamic Go Package Paths with Markers For more complex path generation, you can use markers in go_package_prefix or go_package values:"},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::102","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers","content":"Dynamic Go Package Paths with Markers"},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::103","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers **Available markers:** {{file_path}} - Full file path without .proto extension - Example: internal/cms/as.proto → internal/cms/as {{file_dir}} - Directory path only, without filename","content":"Dynamic Go Package Paths with Markers **Available markers:** {{file_path}} - Full file path without .proto extension - Example: internal/cms/as.proto → internal/cms/as {{file_dir}} - Directory path only, without filename - Example: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Directory path with prefix removed, and base filename without _service/_grpc suffixes - Example: {{file_dir_without:internal/}} for internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Full file path with prefix removed - Example: {{file_path_without:internal/}} for internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::module-specific-overrides::104","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides Apply different options to different modules:","content":"Module-Specific Overrides Apply different options to different modules:"},{"id":"cli/generator/generator::module-specific-overrides::105","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides module matches the EasyP module source exactly: the dependency or git_repo.url value before @version (for example github.com/mycompany/internal-protos or https://github.com/mycompany/internal-pr","content":"Module-Specific Overrides module matches the EasyP module source exactly: the dependency or git_repo.url value before @version (for example github.com/mycompany/internal-protos or https://github.com/mycompany/internal-protos). It is not the Go module path from go.mod."},{"id":"cli/generator/generator::module-specific-overrides::106","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides package matches the protobuf package declaration exactly, for example acme.weather.v1.","content":"Module-Specific Overrides package matches the protobuf package declaration exactly, for example acme.weather.v1."},{"id":"cli/generator/generator::package-specific-overrides::107","title":"Generator","section":"Package-Specific Overrides","path":"/docs/guide/cli/generator/generator#package-specific-overrides","headings":["Package-Specific Overrides"],"excerpt":"Package-Specific Overrides Apply different options to files from a specific protobuf package:","content":"Package-Specific Overrides Apply different options to files from a specific protobuf package:"},{"id":"cli/generator/generator::disabling-for-external-dependencies::108","title":"Generator","section":"Disabling for External Dependencies","path":"/docs/guide/cli/generator/generator#disabling-for-external-dependencies","headings":["Disabling for External Dependencies"],"excerpt":"Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set:","content":"Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set:"},{"id":"cli/generator/generator::disabling-for-external-dependencies::109","title":"Generator","section":"Disabling for External Dependencies","path":"/docs/guide/cli/generator/generator#disabling-for-external-dependencies","headings":["Disabling for External Dependencies"],"excerpt":"Disabling for External Dependencies","content":"Disabling for External Dependencies"},{"id":"cli/generator/generator::javascript-type-safety::110","title":"Generator","section":"JavaScript Type Safety","path":"/docs/guide/cli/generator/generator#javascript-type-safety","headings":["JavaScript Type Safety"],"excerpt":"JavaScript Type Safety Set jstype to JS_STRING for all 64-bit integer fields to prevent precision loss in JavaScript:","content":"JavaScript Type Safety Set jstype to JS_STRING for all 64-bit integer fields to prevent precision loss in JavaScript:"},{"id":"cli/generator/generator::path-matching::111","title":"Generator","section":"Path Matching","path":"/docs/guide/cli/generator/generator#path-matching","headings":["Path Matching"],"excerpt":"Path Matching Path matching in managed mode uses prefix-based matching (same as buf):","content":"Path Matching Path matching in managed mode uses prefix-based matching (same as buf):"},{"id":"cli/generator/generator::path-matching::112","title":"Generator","section":"Path Matching","path":"/docs/guide/cli/generator/generator#path-matching","headings":["Path Matching"],"excerpt":"Path Matching **Directory path** (ending with /): Matches all files in that directory and subdirectories - Example: path: \"internal/cms/\" matches internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.pr","content":"Path Matching **Directory path** (ending with /): Matches all files in that directory and subdirectories - Example: path: \"internal/cms/\" matches internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Exact file path** (ending with .proto): Matches only that specific file - Example: path: \"internal/cms/as.proto\" matches only internal/cms/as.proto **Prefix path** (no trailing / or .proto): Uses prefix matching (not directory-aware) - Example: path: \"internal/cms\" matches internal/cms/as.proto but also internal/cmsv2/file.proto"},{"id":"cli/generator/generator::rule-precedence::113","title":"Generator","section":"Rule Precedence","path":"/docs/guide/cli/generator/generator#rule-precedence","headings":["Rule Precedence"],"excerpt":"Rule Precedence When multiple rules match the same file or field, the following precedence applies:","content":"Rule Precedence When multiple rules match the same file or field, the following precedence applies:"},{"id":"cli/generator/generator::rule-precedence::114","title":"Generator","section":"Rule Precedence","path":"/docs/guide/cli/generator/generator#rule-precedence","headings":["Rule Precedence"],"excerpt":"Rule Precedence **Disable rules** take precedence - if an option is disabled, it won't be applied **Override rules** are applied in order - the last matching rule wins **Default values** are applied only if no override m","content":"Rule Precedence **Disable rules** take precedence - if an option is disabled, it won't be applied **Override rules** are applied in order - the last matching rule wins **Default values** are applied only if no override matches and the option isn't disabled"},{"id":"cli/generator/generator::compatibility-with-buf::115","title":"Generator","section":"Compatibility with buf","path":"/docs/guide/cli/generator/generator#compatibility-with-buf","headings":["Compatibility with buf"],"excerpt":"Compatibility with buf EasyP's managed mode is compatible with buf's managed mode. The same configuration format and behavior apply, making it easy to migrate between tools or use both in the same workflow.","content":"Compatibility with buf EasyP's managed mode is compatible with buf's managed mode. The same configuration format and behavior apply, making it easy to migrate between tools or use both in the same workflow."},{"id":"cli/generator/generator::descriptor-set-generation::116","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Descriptor Set Generation **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set-generation::117","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation EasyP supports generating binary FileDescriptorSet files using the --descriptor_set_out flag. This allows you to create self-describing protobuf messages that include schema information alongsid","content":"Descriptor Set Generation EasyP supports generating binary FileDescriptorSet files using the --descriptor_set_out flag. This allows you to create self-describing protobuf messages that include schema information alongside the data."},{"id":"cli/generator/generator::descriptor-set-generation::118","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **CLI flags:**","content":"Descriptor Set Generation **CLI flags:**"},{"id":"cli/generator/generator::descriptor-set-generation::119","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation --descriptor_set_out - Output path for the binary FileDescriptorSet --include_imports - Include all transitive dependencies in the FileDescriptorSet","content":"Descriptor Set Generation --descriptor_set_out - Output path for the binary FileDescriptorSet --include_imports - Include all transitive dependencies in the FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set-generation::120","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **Example:**","content":"Descriptor Set Generation **Example:**"},{"id":"cli/generator/generator::descriptor-set-generation::121","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation ```bash Generate descriptor set with only target files easyp generate --descriptor_set_out=./schema.pb","content":"Descriptor Set Generation ```bash Generate descriptor set with only target files easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set-generation::122","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation Generate descriptor set with all dependencies easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Descriptor Set Generation Generate descriptor set with all dependencies easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set-generation::123","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation Self-describing messages are useful for dynamic message parsing, runtime schema validation, schema registries, and building generic gRPC clients. For more information, see the Protocol Buffers d","content":"Descriptor Set Generation Self-describing messages are useful for dynamic message parsing, runtime schema validation, schema registries, and building generic gRPC clients. For more information, see the Protocol Buffers documentation on self-description."},{"id":"cli/generator/generator::package-manager-integration::124","title":"Generator","section":"Package Manager Integration","path":"/docs/guide/cli/generator/generator#package-manager-integration","headings":["Package Manager Integration"],"excerpt":"Package Manager Integration One of EasyP's most powerful features is the seamless integration between the package manager and code generator. This integration eliminates the common problem of managing proto dependencies ","content":"Package Manager Integration One of EasyP's most powerful features is the seamless integration between the package manager and code generator. This integration eliminates the common problem of managing proto dependencies manually and ensures that your generated code always has access to the correct versions of imported proto files."},{"id":"cli/generator/generator::package-manager-integration::125","title":"Generator","section":"Package Manager Integration","path":"/docs/guide/cli/generator/generator#package-manager-integration","headings":["Package Manager Integration"],"excerpt":"Package Manager Integration **Key benefits:** **Automatic dependency resolution**: No need to manually manage proto import paths **Version consistency**: Dependencies are locked to specific versions via easyp.lock **Tran","content":"Package Manager Integration **Key benefits:** **Automatic dependency resolution**: No need to manually manage proto import paths **Version consistency**: Dependencies are locked to specific versions via easyp.lock **Transitive dependencies**: EasyP handles dependencies of dependencies automatically **Performance**: Local caching means dependencies are downloaded once and reused"},{"id":"cli/generator/generator::automatic-dependency-resolution::126","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution When you define dependencies in the deps section, the generator automatically includes them in the proto path. This means your proto files can import from these dependencies without any ad","content":"Automatic Dependency Resolution When you define dependencies in the deps section, the generator automatically includes them in the proto path. This means your proto files can import from these dependencies without any additional configuration."},{"id":"cli/generator/generator::automatic-dependency-resolution::127","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution **How it works:** EasyP downloads and caches dependencies based on your deps configuration During generation, these cached proto files are automatically added to the protoc import path You","content":"Automatic Dependency Resolution **How it works:** EasyP downloads and caches dependencies based on your deps configuration During generation, these cached proto files are automatically added to the protoc import path Your proto files can import from dependencies using standard import statements Generated code includes both your local protos and dependency protos when with_imports: true"},{"id":"cli/generator/generator::automatic-dependency-resolution::128","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution Here's a simple example showing how dependency resolution works automatically. Notice that you only need to specify the dependencies once in the deps section:","content":"Automatic Dependency Resolution Here's a simple example showing how dependency resolution works automatically. Notice that you only need to specify the dependencies once in the deps section:"},{"id":"cli/generator/generator::automatic-dependency-resolution::129","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Automatic Dependency Resolution ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::automatic-dependency-resolution::130","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway protos ``","content":"Automatic Dependency Resolution generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway protos ```"},{"id":"cli/generator/generator::dependency-usage-examples::131","title":"Generator","section":"Dependency Usage Examples","path":"/docs/guide/cli/generator/generator#dependency-usage-examples","headings":["Dependency Usage Examples"],"excerpt":"Dependency Usage Examples The following examples demonstrate common patterns for integrating external proto dependencies into your code generation workflow.","content":"Dependency Usage Examples The following examples demonstrate common patterns for integrating external proto dependencies into your code generation workflow."},{"id":"cli/generator/generator::using-google-apis::132","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs Google APIs are among the most commonly used proto dependencies, providing standard types and annotations for REST APIs, field validation, and common data structures.","content":"Using Google APIs Google APIs are among the most commonly used proto dependencies, providing standard types and annotations for REST APIs, field validation, and common data structures."},{"id":"cli/generator/generator::using-google-apis::133","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs **When to use Google APIs:** Building REST APIs with gRPC-Gateway Need standard types like Timestamp, Duration, Any Want to use Google's field behavior annotations Building services that integrate with ","content":"Using Google APIs **When to use Google APIs:** Building REST APIs with gRPC-Gateway Need standard types like Timestamp, Duration, Any Want to use Google's field behavior annotations Building services that integrate with Google Cloud"},{"id":"cli/generator/generator::using-google-apis::134","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs This configuration shows the minimal setup needed to use Google APIs in your proto files:","content":"Using Google APIs This configuration shows the minimal setup needed to use Google APIs in your proto files:"},{"id":"cli/generator/generator::using-google-apis::135","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Using Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::using-google-apis::136","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Using Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::using-google-apis::137","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs **Important:** Always use a pinned version (like common-protos-1_3_1) rather than latest to ensure build reproducibility.","content":"Using Google APIs **Important:** Always use a pinned version (like common-protos-1_3_1) rather than latest to ensure build reproducibility."},{"id":"cli/generator/generator::using-google-apis::138","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs Once configured, your proto files can import and use Google API definitions. Here's an example of a service using HTTP annotations:","content":"Using Google APIs Once configured, your proto files can import and use Google API definitions. Here's an example of a service using HTTP annotations:"},{"id":"cli/generator/generator::using-google-apis::139","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Using Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::using-google-apis::140","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Using Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::using-google-apis::141","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Using Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::using-validation-rules::142","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules Protoc-gen-validate provides powerful field validation capabilities that can be embedded directly in your proto definitions, eliminating the need for separate validation logic in your application c","content":"Using Validation Rules Protoc-gen-validate provides powerful field validation capabilities that can be embedded directly in your proto definitions, eliminating the need for separate validation logic in your application code."},{"id":"cli/generator/generator::using-validation-rules::143","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **When to use validation:** Input validation for API endpoints Database model constraints Configuration file validation Any scenario where data integrity is critical","content":"Using Validation Rules **When to use validation:** Input validation for API endpoints Database model constraints Configuration file validation Any scenario where data integrity is critical"},{"id":"cli/generator/generator::using-validation-rules::144","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **Benefits:** Validation rules are part of the proto definition (single source of truth) Code generation creates validation functions automatically Consistent validation across different languages ","content":"Using Validation Rules **Benefits:** Validation rules are part of the proto definition (single source of truth) Code generation creates validation functions automatically Consistent validation across different languages Better performance than runtime reflection-based validation"},{"id":"cli/generator/generator::using-validation-rules::145","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Using Validation Rules ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::using-validation-rules::146","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true - name: validate-go out: ./gen/go opts: paths: source_relative ```","content":"Using Validation Rules generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true - name: validate-go out: ./gen/go opts: paths: source_relative ```"},{"id":"cli/generator/generator::using-validation-rules::147","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **Note:** You need both the dependency (for proto imports) and the plugin (for code generation) to get full validation support.","content":"Using Validation Rules **Note:** You need both the dependency (for proto imports) and the plugin (for code generation) to get full validation support."},{"id":"cli/generator/generator::using-validation-rules::148","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules Here's how validation rules look in your proto files. The generated code will automatically validate these constraints:","content":"Using Validation Rules Here's how validation rules look in your proto files. The generated code will automatically validate these constraints:"},{"id":"cli/generator/generator::using-validation-rules::149","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules ```proto // proto/user.proto syntax = \"proto3\";","content":"Using Validation Rules ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::using-validation-rules::150","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules import \"validate/validate.proto\";","content":"Using Validation Rules import \"validate/validate.proto\";"},{"id":"cli/generator/generator::using-validation-rules::151","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Using Validation Rules message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::complex-multi-dependency-setup::152","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup This example demonstrates a production-ready configuration that combines multiple dependencies and plugins for a complete API development workflow:","content":"Complex Multi-Dependency Setup This example demonstrates a production-ready configuration that combines multiple dependencies and plugins for a complete API development workflow:"},{"id":"cli/generator/generator::complex-multi-dependency-setup::153","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup ```yaml deps: # Core Google APIs - Standard types and HTTP annotations - github.com/googleapis/googleapis@common-protos-1_3_1 # gRPC Gateway for REST APIs - Enables HTTP/JSON interfaces - g","content":"Complex Multi-Dependency Setup ```yaml deps: # Core Google APIs - Standard types and HTTP annotations - github.com/googleapis/googleapis@common-protos-1_3_1 # gRPC Gateway for REST APIs - Enables HTTP/JSON interfaces - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 # Validation rules - Field-level validation constraints - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Company internal shared types - Common business objects - github.com/mycompany/shared-protos@v1.5.0"},{"id":"cli/generator/generator::complex-multi-dependency-setup::154","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myserv","content":"Complex Multi-Dependency Setup generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myservice with_imports: true # gRPC service stubs - Server and client interfaces - name: go-grpc out: ./gen/go opts: paths: source_relative require_unimplemented_servers: false # REST Gateway - HTTP-to-gRPC proxy code - name: grpc-gateway out: ./gen/go opts: paths: source_relative # OpenAPI documentation - API specification - name: openapiv2 out: ./gen/openapi opts: simple_operation_ids: true # Validation code - Input validation functions - name: validate-go out: ./gen/go opts: paths: source_relative ```"},{"id":"cli/generator/generator::dependency-cache-integration::155","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration The generator leverages EasyP's module cache for fast builds:","content":"Dependency Cache Integration The generator leverages EasyP's module cache for fast builds:"},{"id":"cli/generator/generator::dependency-cache-integration::156","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration ```bash Download dependencies once easyp mod download","content":"Dependency Cache Integration ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::dependency-cache-integration::157","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration Generate code (uses cached dependencies) easyp generate","content":"Dependency Cache Integration Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::dependency-cache-integration::158","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Dependency Cache Integration Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::remote-generation::159","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation Remote generation is a powerful feature that allows you to generate code from proto files hosted in remote Git repositories without requiring a local checkout. This enables true microservices architectu","content":"Remote Generation Remote generation is a powerful feature that allows you to generate code from proto files hosted in remote Git repositories without requiring a local checkout. This enables true microservices architecture where teams can consume each other's APIs without tight coupling."},{"id":"cli/generator/generator::remote-generation::160","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation **Key advantages:** **Decoupled development**: Teams can work independently while consuming each other's APIs **Version control**: Pin to specific versions of external APIs for stability **Reduced repos","content":"Remote Generation **Key advantages:** **Decoupled development**: Teams can work independently while consuming each other's APIs **Version control**: Pin to specific versions of external APIs for stability **Reduced repository size**: No need to vendor or submodule external proto files **Automatic updates**: Easy to update to newer versions when ready"},{"id":"cli/generator/generator::remote-generation::161","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation **Best practices:** Always use tagged versions in production environments Test with latest versions in development, but pin in production Use semantic versioning when available for easier dependency man","content":"Remote Generation **Best practices:** Always use tagged versions in production environments Test with latest versions in development, but pin in production Use semantic versioning when available for easier dependency management Consider the network implications for CI/CD systems"},{"id":"cli/generator/generator::remote-proto-sources::162","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources Generate from remote repositories directly. This is particularly useful in microservices architectures where different teams own different proto definitions.","content":"Remote Proto Sources Generate from remote repositories directly. This is particularly useful in microservices architectures where different teams own different proto definitions."},{"id":"cli/generator/generator::remote-proto-sources::163","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources **Typical workflow:** Team A publishes proto definitions in a Git repository with proper versioning Team B references these protos in their easyp.yaml configuration During generation, EasyP automatic","content":"Remote Proto Sources **Typical workflow:** Team A publishes proto definitions in a Git repository with proper versioning Team B references these protos in their easyp.yaml configuration During generation, EasyP automatically fetches and uses the remote protos Generated code includes client libraries for Team A's services"},{"id":"cli/generator/generator::remote-proto-sources::164","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources Here's a practical example showing how to combine local and remote proto sources in a single generation configuration:","content":"Remote Proto Sources Here's a practical example showing how to combine local and remote proto sources in a single generation configuration:"},{"id":"cli/generator/generator::remote-generation-use-cases::165","title":"Generator","section":"Remote Generation Use Cases","path":"/docs/guide/cli/generator/generator#remote-generation-use-cases","headings":["Remote Generation Use Cases"],"excerpt":"Remote Generation Use Cases These examples demonstrate real-world scenarios where remote generation provides significant value in distributed development environments.","content":"Remote Generation Use Cases These examples demonstrate real-world scenarios where remote generation provides significant value in distributed development environments."},{"id":"cli/generator/generator::multi-team-development::166","title":"Generator","section":"Multi-Team Development","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Multi-Team Development"],"excerpt":"Multi-Team Development Multi-team development is where remote generation truly shines. Instead of coordinating shared repositories or complex dependency management, teams can independently evolve their APIs while consume","content":"Multi-Team Development Multi-team development is where remote generation truly shines. Instead of coordinating shared repositories or complex dependency management, teams can independently evolve their APIs while consumers automatically get updates through versioned dependencies."},{"id":"cli/generator/generator::multi-team-development::167","title":"Generator","section":"Multi-Team Development","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Multi-Team Development"],"excerpt":"Multi-Team Development This pattern is especially valuable in large organizations where: Teams have different release cycles and development velocities API ownership is clearly defined but consumption is widespread You w","content":"Multi-Team Development This pattern is especially valuable in large organizations where: Teams have different release cycles and development velocities API ownership is clearly defined but consumption is widespread You want to avoid the overhead of coordinating shared proto repositories Different teams use different technology stacks but need to communicate"},{"id":"cli/generator/generator::vendor-api-integration::168","title":"Generator","section":"Vendor API Integration","path":"/docs/guide/cli/generator/generator#vendor-api-integration","headings":["Vendor API Integration"],"excerpt":"Vendor API Integration Many vendors now provide proto definitions for their APIs, enabling strongly-typed client generation instead of relying on hand-written HTTP clients. This approach provides better type safety, auto","content":"Vendor API Integration Many vendors now provide proto definitions for their APIs, enabling strongly-typed client generation instead of relying on hand-written HTTP clients. This approach provides better type safety, automatic serialization, and often better performance."},{"id":"cli/generator/generator::vendor-api-integration::169","title":"Generator","section":"Vendor API Integration","path":"/docs/guide/cli/generator/generator#vendor-api-integration","headings":["Vendor API Integration"],"excerpt":"Vendor API Integration Benefits of using vendor proto definitions: **Type safety**: Compile-time checking of API calls and data structures **Automatic updates**: New API features become available through version updates ","content":"Vendor API Integration Benefits of using vendor proto definitions: **Type safety**: Compile-time checking of API calls and data structures **Automatic updates**: New API features become available through version updates **Consistency**: Same interface patterns across different vendor integrations **Performance**: Binary serialization is often faster than JSON **Documentation**: Proto files serve as authoritative API documentation"},{"id":"cli/generator/generator::commands::170","title":"Generator","section":"Commands","path":"/docs/guide/cli/generator/generator#commands","headings":["Commands"],"excerpt":"Commands The EasyP command-line interface provides flexible options for running code generation with different configurations and environments.","content":"Commands The EasyP command-line interface provides flexible options for running code generation with different configurations and environments."},{"id":"cli/generator/generator::basic-generation::171","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation These are the most commonly used command patterns for everyday development and production use:","content":"Basic Generation These are the most commonly used command patterns for everyday development and production use:"},{"id":"cli/generator/generator::basic-generation::172","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Basic Generation ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::basic-generation::173","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Basic Generation Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::basic-generation::174","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Basic Generation Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::basic-generation::175","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Basic Generation Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::integration-with-package-manager::176","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager EasyP's package manager integration means you can either explicitly manage dependencies or let the generator handle them automatically. The explicit approach gives you more control, while","content":"Integration with Package Manager EasyP's package manager integration means you can either explicitly manage dependencies or let the generator handle them automatically. The explicit approach gives you more control, while the automatic approach is more convenient:"},{"id":"cli/generator/generator::integration-with-package-manager::177","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager ```bash Explicit workflow - Better for CI/CD and when you want to cache dependencies easyp mod download # Download and cache dependencies first easyp generate # Generate code using cached","content":"Integration with Package Manager ```bash Explicit workflow - Better for CI/CD and when you want to cache dependencies easyp mod download # Download and cache dependencies first easyp generate # Generate code using cached dependencies"},{"id":"cli/generator/generator::integration-with-package-manager::178","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Integration with Package Manager Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage These advanced usage patterns are useful for specific deployment scenarios, debugging, or when you need fine-grained control over the generation process:","content":"Advanced Usage These advanced usage patterns are useful for specific deployment scenarios, debugging, or when you need fine-grained control over the generation process:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage ```bash Generate from specific input directory - Override config file settings easyp generate --path=./api/proto","content":"Advanced Usage ```bash Generate from specific input directory - Override config file settings easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage Generate using vendored dependencies - For offline builds or Docker containers easyp mod vendor easyp generate","content":"Advanced Usage Generate using vendored dependencies - For offline builds or Docker containers easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage Generate from a custom project root - Useful in monorepos or nested workdirs easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Advanced Usage Generate from a custom project root - Useful in monorepos or nested workdirs easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Generator","section":"Common Patterns","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Common Patterns"],"excerpt":"Common Patterns These patterns represent real-world scenarios and best practices for organizing code generation in different project structures.","content":"Common Patterns These patterns represent real-world scenarios and best practices for organizing code generation in different project structures."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation Multi-language generation is essential for organizations using different technologies across their stack. EasyP makes it easy to generate consistent client libraries and types for multiple progr","content":"Multi-Language Generation Multi-language generation is essential for organizations using different technologies across their stack. EasyP makes it easy to generate consistent client libraries and types for multiple programming languages from the same proto definitions."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Common scenarios:** **Full-stack applications**: Go/Java backend with TypeScript frontend for web apps **Data platforms**: Go services with Python data science tools and analysis scripts **Mic","content":"Multi-Language Generation **Common scenarios:** **Full-stack applications**: Go/Java backend with TypeScript frontend for web apps **Data platforms**: Go services with Python data science tools and analysis scripts **Microservices**: Different services implemented in optimal languages for their domain **Client libraries**: Providing SDKs in multiple languages for external developers **Legacy integration**: Modern gRPC services with legacy systems using different languages"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Performance considerations:** Each plugin runs independently, so generation time scales linearly with plugin count Consider using parallel execution (make -j4) for large numbers of plugins Out","content":"Multi-Language Generation **Performance considerations:** Each plugin runs independently, so generation time scales linearly with plugin count Consider using parallel execution (make -j4) for large numbers of plugins Output directories should be organized hierarchically to avoid file conflicts Some plugins are faster than others - profile your build to identify bottlenecks"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Maintenance benefits:** Single source of truth for API definitions prevents schema drift Consistent types across all languages reduce integration bugs Automatic synchronization when proto defi","content":"Multi-Language Generation **Maintenance benefits:** Single source of truth for API definitions prevents schema drift Consistent types across all languages reduce integration bugs Automatic synchronization when proto definitions change eliminates manual updates Reduced chance of API drift between different language implementations Easier refactoring since changes propagate to all generated code"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation This example shows a typical multi-language setup for a full-stack application with backend services, web frontend, data analysis, and documentation:","content":"Multi-Language Generation This example shows a typical multi-language setup for a full-stack application with backend services, web frontend, data analysis, and documentation:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Organization tip:** Use separate output directories for each language to avoid file conflicts and make it easier to integrate with language-specific build systems.","content":"Multi-Language Generation **Organization tip:** Use separate output directories for each language to avoid file conflicts and make it easier to integrate with language-specific build systems."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation The EasyP generator provides a comprehensive solution for protocol buffer code generation, supporting everything from simple local development to complex enterprise multi-language workflows with","content":"Multi-Language Generation The EasyP generator provides a comprehensive solution for protocol buffer code generation, supporting everything from simple local development to complex enterprise multi-language workflows with remote dependencies."},{"id":"cli/linter/linter::why-use-a-linter-for-proto-files::0","title":"Linter","section":"Why Use a Linter for Proto Files?","path":"/docs/guide/cli/linter/linter#why-use-a-linter-for-proto-files","headings":["Why Use a Linter for Proto Files?"],"excerpt":"Why Use a Linter for Proto Files? Linters play a crucial role in modern software development, particularly for proto files. By enforcing style and formatting rules, linters help maintain code quality, reduce potential bu","content":"Why Use a Linter for Proto Files? Linters play a crucial role in modern software development, particularly for proto files. By enforcing style and formatting rules, linters help maintain code quality, reduce potential bugs, and ensure that the codebase is clean and readable. This leads to several benefits:"},{"id":"cli/linter/linter::why-use-a-linter-for-proto-files::1","title":"Linter","section":"Why Use a Linter for Proto Files?","path":"/docs/guide/cli/linter/linter#why-use-a-linter-for-proto-files","headings":["Why Use a Linter for Proto Files?"],"excerpt":"Why Use a Linter for Proto Files? **Reduced Development Costs:** Linters catch errors early in the development cycle, saving time and resources that would be spent on debugging and fixing issues later. **Improved Team Co","content":"Why Use a Linter for Proto Files? **Reduced Development Costs:** Linters catch errors early in the development cycle, saving time and resources that would be spent on debugging and fixing issues later. **Improved Team Collaboration:** A standardized codebase makes it easier for team members to understand and work with each other's code, facilitating a smoother collaborative environment. **Business Efficiency:** Teams using linters often produce higher quality code, which translates to fewer production issues and maintenance costs. This makes businesses that adopt linting practices more competitive and cost-effective."},{"id":"cli/linter/linter::configuration-reference::2","title":"Linter","section":"Configuration Reference","path":"/docs/guide/cli/linter/linter#configuration-reference","headings":["Configuration Reference"],"excerpt":"Configuration Reference EasyP linter provides flexible configuration options to adapt to different project requirements. All configuration is done through the lint section in your easyp.yaml file.","content":"Configuration Reference EasyP linter provides flexible configuration options to adapt to different project requirements. All configuration is done through the lint section in your easyp.yaml file."},{"id":"cli/linter/linter::complete-configuration-example::3","title":"Linter","section":"Complete Configuration Example","path":"/docs/guide/cli/linter/linter#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example","content":"Complete Configuration Example"},{"id":"cli/linter/linter::use-string::4","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Specifies which linter rules or rule categories to apply. You can mix individual rules with predefined categories.","content":"use ([]string) Specifies which linter rules or rule categories to apply. You can mix individual rules with predefined categories."},{"id":"cli/linter/linter::use-string::5","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Available categories:** **MINIMAL**: Basic package consistency checks **BASIC**: Naming conventions and usage patterns **DEFAULT**: Recommended rules for most projects **COMMENTS**: Comment presence and ","content":"use ([]string) **Available categories:** **MINIMAL**: Basic package consistency checks **BASIC**: Naming conventions and usage patterns **DEFAULT**: Recommended rules for most projects **COMMENTS**: Comment presence and formatting **UNARY_RPC**: Restrictions on streaming RPCs"},{"id":"cli/linter/linter::use-string::6","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Individual rules**: Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Individual rules**: Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::7","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Examples:** ```yaml Use predefined categories use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Examples:** ```yaml Use predefined categories use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::8","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Mix categories with individual rules use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Mix categories with individual rules use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::9","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Use only specific rules use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Use only specific rules use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) Defines the required suffix for zero-value enum entries. This enforces a consistent naming pattern for the default enum value.","content":"enum_zero_value_suffix (string) Defines the required suffix for zero-value enum entries. This enforces a consistent naming pattern for the default enum value."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::12","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) **Example:**","content":"enum_zero_value_suffix (string) **Example:**"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::13","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) With this setting, enum definitions must follow this pattern:","content":"enum_zero_value_suffix (string) With this setting, enum definitions must follow this pattern:"},{"id":"cli/linter/linter::service_suffix-string::14","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Specifies the required suffix for service names. This ensures consistent service naming across your project.","content":"service_suffix (string) Specifies the required suffix for service names. This ensures consistent service naming across your project."},{"id":"cli/linter/linter::service_suffix-string::15","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"Service\", \"API\", \"Svc\"","content":"service_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"Service\", \"API\", \"Svc\""},{"id":"cli/linter/linter::service_suffix-string::16","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) **Example:**","content":"service_suffix (string) **Example:**"},{"id":"cli/linter/linter::service_suffix-string::17","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) With this setting, service definitions must follow this pattern:","content":"service_suffix (string) With this setting, service definitions must follow this pattern:"},{"id":"cli/linter/linter::ignore-string::18","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Lists directories or file paths to completely exclude from linting. Supports glob patterns and relative paths from the project root.","content":"ignore ([]string) Lists directories or file paths to completely exclude from linting. Supports glob patterns and relative paths from the project root."},{"id":"cli/linter/linter::ignore-string::19","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** Third-party or vendor proto files Generated proto files Legacy code being phased out Test fixtures that intentionally violate rules","content":"ignore ([]string) **Use cases:** Third-party or vendor proto files Generated proto files Legacy code being phased out Test fixtures that intentionally violate rules"},{"id":"cli/linter/linter::ignore-string::20","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Examples:**","content":"ignore ([]string) **Examples:**"},{"id":"cli/linter/linter::except-string::21","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Disables specific rules globally across the entire project. Use this when certain rules don't fit your project's conventions.","content":"except ([]string) Disables specific rules globally across the entire project. Use this when certain rules don't fit your project's conventions."},{"id":"cli/linter/linter::except-string::22","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) **When to use:** Legacy projects with established naming conventions Projects with specific style requirements Gradual adoption of linting rules","content":"except ([]string) **When to use:** Legacy projects with established naming conventions Projects with specific style requirements Gradual adoption of linting rules"},{"id":"cli/linter/linter::except-string::23","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) **Examples:**","content":"except ([]string) **Examples:**"},{"id":"cli/linter/linter::allow_comment_ignores-bool::24","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) Enables or disables the ability to ignore specific rules using inline comments in proto files.","content":"allow_comment_ignores (bool) Enables or disables the ability to ignore specific rules using inline comments in proto files."},{"id":"cli/linter/linter::allow_comment_ignores-bool::25","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) **Default**: false **Recommended**: true for flexibility during development","content":"allow_comment_ignores (bool) **Default**: false **Recommended**: true for flexibility during development"},{"id":"cli/linter/linter::allow_comment_ignores-bool::26","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) **Example:**","content":"allow_comment_ignores (bool) **Example:**"},{"id":"cli/linter/linter::allow_comment_ignores-bool::27","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) When enabled, you can use comments to ignore rules on specific elements:","content":"allow_comment_ignores (bool) When enabled, you can use comments to ignore rules on specific elements:"},{"id":"cli/linter/linter::ignore_only-mapstringstring::28","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) Allows you to disable specific rules only for certain files or directories, while keeping them active elsewhere.","content":"ignore_only (mapstringstring) Allows you to disable specific rules only for certain files or directories, while keeping them active elsewhere."},{"id":"cli/linter/linter::ignore_only-mapstringstring::29","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Use cases:** Legacy code that can't be easily updated Third-party protos with different conventions Generated code that doesn't follow your style Gradual migration strategies","content":"ignore_only (mapstringstring) **Use cases:** Legacy code that can't be easily updated Third-party protos with different conventions Generated code that doesn't follow your style Gradual migration strategies"},{"id":"cli/linter/linter::ignore_only-mapstringstring::30","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Format**: rule_name: [list_of_paths]","content":"ignore_only (mapstringstring) **Format**: rule_name: [list_of_paths]"},{"id":"cli/linter/linter::ignore_only-mapstringstring::31","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Examples:**","content":"ignore_only (mapstringstring) **Examples:**"},{"id":"cli/linter/linter::comment-based-rule-ignoring::32","title":"Linter","section":"Comment-Based Rule Ignoring","path":"/docs/guide/cli/linter/linter#comment-based-rule-ignoring","headings":["Comment-Based Rule Ignoring"],"excerpt":"Comment-Based Rule Ignoring When allow_comment_ignores is enabled, you can use inline comments to ignore specific linter rules for individual proto elements. This provides fine-grained control over rule enforcement.","content":"Comment-Based Rule Ignoring When allow_comment_ignores is enabled, you can use inline comments to ignore specific linter rules for individual proto elements. This provides fine-grained control over rule enforcement."},{"id":"cli/linter/linter::supported-comment-formats::33","title":"Linter","section":"Supported Comment Formats","path":"/docs/guide/cli/linter/linter#supported-comment-formats","headings":["Supported Comment Formats"],"excerpt":"Supported Comment Formats EasyP supports two comment formats for maximum compatibility:","content":"Supported Comment Formats EasyP supports two comment formats for maximum compatibility:"},{"id":"cli/linter/linter::ignoring-message-and-field-rules::34","title":"Linter","section":"Ignoring Message and Field Rules","path":"/docs/guide/cli/linter/linter#ignoring-message-and-field-rules","headings":["Ignoring Message and Field Rules"],"excerpt":"Ignoring Message and Field Rules","content":"Ignoring Message and Field Rules"},{"id":"cli/linter/linter::best-practices-for-comment-ignores::35","title":"Linter","section":"Best Practices for Comment Ignores","path":"/docs/guide/cli/linter/linter#best-practices-for-comment-ignores","headings":["Best Practices for Comment Ignores"],"excerpt":"Best Practices for Comment Ignores","content":"Best Practices for Comment Ignores"},{"id":"cli/linter/linter::use-sparingly::36","title":"Linter","section":"Use Sparingly","path":"/docs/guide/cli/linter/linter#use-sparingly","headings":["Use Sparingly"],"excerpt":"Use Sparingly Comment ignores should be the exception, not the rule. Overuse indicates that your linting configuration may need adjustment.","content":"Use Sparingly Comment ignores should be the exception, not the rule. Overuse indicates that your linting configuration may need adjustment."},{"id":"cli/linter/linter::add-explanatory-comments::37","title":"Linter","section":"Add Explanatory Comments","path":"/docs/guide/cli/linter/linter#add-explanatory-comments","headings":["Add Explanatory Comments"],"excerpt":"Add Explanatory Comments Always explain why you're ignoring a rule to help future maintainers understand the decision.","content":"Add Explanatory Comments Always explain why you're ignoring a rule to help future maintainers understand the decision."},{"id":"cli/linter/linter::prefer-configuration-over-comments::38","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments When multiple files need the same rule ignored, use ignore_only configuration instead of individual comments.","content":"Prefer Configuration Over Comments When multiple files need the same rule ignored, use ignore_only configuration instead of individual comments."},{"id":"cli/linter/linter::prefer-configuration-over-comments::39","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments **Instead of:** ```proto // In file1.proto // buf:lint:ignore COMMENT_SERVICE service API1 { ... }","content":"Prefer Configuration Over Comments **Instead of:** ```proto // In file1.proto // buf:lint:ignore COMMENT_SERVICE service API1 { ... }"},{"id":"cli/linter/linter::prefer-configuration-over-comments::40","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments // In file2.proto // buf:lint:ignore COMMENT_SERVICE service API2 { ... } ```","content":"Prefer Configuration Over Comments // In file2.proto // buf:lint:ignore COMMENT_SERVICE service API2 { ... } ```"},{"id":"cli/linter/linter::prefer-configuration-over-comments::41","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments **Use:**","content":"Prefer Configuration Over Comments **Use:**"},{"id":"cli/linter/linter::linter-categories::42","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories To accommodate different project needs and preferences, EasyP linter provides predefined rule categories. These categories group together various rules, allowing teams to quickly select the level of str","content":"Linter Categories To accommodate different project needs and preferences, EasyP linter provides predefined rule categories. These categories group together various rules, allowing teams to quickly select the level of strictness or areas they want to focus on during linting."},{"id":"cli/linter/linter::linter-categories::43","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories **When to use each category:**","content":"Linter Categories **When to use each category:**"},{"id":"cli/linter/linter::linter-categories::44","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories **MINIMAL:** Essential for any proto project - ensures basic consistency and prevents fundamental issues **BASIC:** Recommended for most projects - enforces common naming conventions and best practices ","content":"Linter Categories **MINIMAL:** Essential for any proto project - ensures basic consistency and prevents fundamental issues **BASIC:** Recommended for most projects - enforces common naming conventions and best practices **DEFAULT:** Additional quality checks - useful for mature projects with established workflows **COMMENTS:** Documentation requirements - important for public APIs and team collaboration **UNARY_RPC:** Streaming restrictions - use when your architecture requires only unary RPCs"},{"id":"cli/linter/linter::linter-categories::45","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories The available categories are: **MINIMAL:** Basic checks to ensure package consistency. **BASIC:** Additional checks for naming conventions and usage patterns. **DEFAULT:** A set of default rules that mo","content":"Linter Categories The available categories are: **MINIMAL:** Basic checks to ensure package consistency. **BASIC:** Additional checks for naming conventions and usage patterns. **DEFAULT:** A set of default rules that most projects should use. **COMMENTS:** Ensures that comments are present and properly formatted. **UNARY_RPC:** Specific rules for unary RPC services."},{"id":"cli/linter/linter::rule-groupings::46","title":"Linter","section":"Rule Groupings","path":"/docs/guide/cli/linter/linter#rule-groupings","headings":["Rule Groupings"],"excerpt":"Rule Groupings Below are the rule groupings under each category:","content":"Rule Groupings Below are the rule groupings under each category:"},{"id":"cli/linter/linter::minimal::47","title":"Linter","section":"MINIMAL","path":"/docs/guide/cli/linter/linter#minimal","headings":["MINIMAL"],"excerpt":"MINIMAL DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY","content":"MINIMAL DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY"},{"id":"cli/linter/linter::basic::48","title":"Linter","section":"BASIC","path":"/docs/guide/cli/linter/linter#basic","headings":["BASIC"],"excerpt":"BASIC ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNA","content":"BASIC ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNAKE_CASE PACKAGE_SAME_CSHARP_NAMESPACE PACKAGE_SAME_GO_PACKAGE PACKAGE_SAME_JAVA_MULTIPLE_FILES PACKAGE_SAME_JAVA_PACKAGE PACKAGE_SAME_PHP_NAMESPACE PACKAGE_SAME_RUBY_PACKAGE PACKAGE_SAME_SWIFT_PREFIX RPC_PASCAL_CASE SERVICE_PASCAL_CASE"},{"id":"cli/linter/linter::default::49","title":"Linter","section":"DEFAULT","path":"/docs/guide/cli/linter/linter#default","headings":["DEFAULT"],"excerpt":"DEFAULT ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX","content":"DEFAULT ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX"},{"id":"cli/linter/linter::comments::50","title":"Linter","section":"COMMENTS","path":"/docs/guide/cli/linter/linter#comments","headings":["COMMENTS"],"excerpt":"COMMENTS COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE","content":"COMMENTS COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE"},{"id":"cli/linter/linter::unary_rpc::51","title":"Linter","section":"UNARY_RPC","path":"/docs/guide/cli/linter/linter#unary_rpc","headings":["UNARY_RPC"],"excerpt":"UNARY_RPC RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING","content":"UNARY_RPC RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING"},{"id":"cli/linter/linter::conclusion::52","title":"Linter","section":"Conclusion","path":"/docs/guide/cli/linter/linter#conclusion","headings":["Conclusion"],"excerpt":"Conclusion Adopting the EasyP linter for your proto files can significantly enhance your development workflow, code quality, and overall project maintainability. With full compatibility with the Buf linter, teams can eas","content":"Conclusion Adopting the EasyP linter for your proto files can significantly enhance your development workflow, code quality, and overall project maintainability. With full compatibility with the Buf linter, teams can easily migrate and start benefiting from our tool's robust features and flexible configuration options."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"This rule checks that enum values have a comment.","content":"This rule checks that enum values have a comment."},{"id":"cli/linter/rules/comment-enum-value::bad::1","title":"COMMENT_ENUM_VALUE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum-value#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::bad::2","title":"COMMENT_ENUM_VALUE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum-value#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum-value::good::3","title":"COMMENT_ENUM_VALUE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum-value#good","headings":["Good"],"excerpt":"Good enum Foo { // BAR value for bar logic // [!code focus] BAR = 0; // BAZ value for baz logic // [!code focus] BAZ = 1; } ```","content":"Good enum Foo { // BAR value for bar logic // [!code focus] BAR = 0; // BAZ value for baz logic // [!code focus] BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum::top::0","title":"COMMENT_ENUM","path":"/docs/guide/cli/linter/rules/comment-enum","headings":[],"excerpt":"This rule checks that enum has a comment.","content":"This rule checks that enum has a comment."},{"id":"cli/linter/rules/comment-enum::bad::1","title":"COMMENT_ENUM","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum::bad::2","title":"COMMENT_ENUM","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum::good::3","title":"COMMENT_ENUM","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum::good::4","title":"COMMENT_ENUM","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum#good","headings":["Good"],"excerpt":"Good // Foo enum for bar and baz logic // [!code focus] enum Foo { BAR = 0; BAZ = 1; } ```","content":"Good // Foo enum for bar and baz logic // [!code focus] enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-field::top::0","title":"COMMENT_FIELD","path":"/docs/guide/cli/linter/rules/comment-field","headings":[],"excerpt":"This rule checks that all message fields have a comment.","content":"This rule checks that all message fields have a comment."},{"id":"cli/linter/rules/comment-field::bad::1","title":"COMMENT_FIELD","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-field#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-field::bad::2","title":"COMMENT_FIELD","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-field#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; string baz = 2; } ```","content":"Bad message Foo { string bar = 1; string baz = 2; } ```"},{"id":"cli/linter/rules/comment-field::good::3","title":"COMMENT_FIELD","section":"Good","path":"/docs/guide/cli/linter/rules/comment-field#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-field::good::4","title":"COMMENT_FIELD","section":"Good","path":"/docs/guide/cli/linter/rules/comment-field#good","headings":["Good"],"excerpt":"Good message Foo { // bar field for bar logic // [!code focus] string bar = 1; // baz field for baz logic // [!code focus] string baz = 2; } ```","content":"Good message Foo { // bar field for bar logic // [!code focus] string bar = 1; // baz field for baz logic // [!code focus] string baz = 2; } ```"},{"id":"cli/linter/rules/comment-message::top::0","title":"COMMENT_MESSAGE","path":"/docs/guide/cli/linter/rules/comment-message","headings":[],"excerpt":"This rule checks that message has a comment.","content":"This rule checks that message has a comment."},{"id":"cli/linter/rules/comment-message::bad::1","title":"COMMENT_MESSAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-message#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; string baz = 2; } ```","content":"Bad message Foo { string bar = 1; string baz = 2; } ```"},{"id":"cli/linter/rules/comment-message::good::2","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good // Foo message for bar and baz logic // [!code focus] message Foo { // bar field for bar logic string bar = 1; // baz field for baz logic string baz = 2; } ```","content":"Good // Foo message for bar and baz logic // [!code focus] message Foo { // bar field for bar logic string bar = 1; // baz field for baz logic string baz = 2; } ```"},{"id":"cli/linter/rules/comment-oneof::top::0","title":"COMMENT_ONEOF","path":"/docs/guide/cli/linter/rules/comment-oneof","headings":[],"excerpt":"This rule checks that oneof has a comment.","content":"This rule checks that oneof has a comment."},{"id":"cli/linter/rules/comment-oneof::bad::1","title":"COMMENT_ONEOF","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-oneof#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-oneof::bad::2","title":"COMMENT_ONEOF","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-oneof#bad","headings":["Bad"],"excerpt":"Bad message Foo { oneof bar { string baz = 1; string qux = 2; } } ```","content":"Bad message Foo { oneof bar { string baz = 1; string qux = 2; } } ```"},{"id":"cli/linter/rules/comment-oneof::good::3","title":"COMMENT_ONEOF","section":"Good","path":"/docs/guide/cli/linter/rules/comment-oneof#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-oneof::good::4","title":"COMMENT_ONEOF","section":"Good","path":"/docs/guide/cli/linter/rules/comment-oneof#good","headings":["Good"],"excerpt":"Good message Foo { // bar oneof for baz and qux logic // [!code focus] oneof bar { string baz = 1; string qux = 2; } } ```","content":"Good message Foo { // bar oneof for baz and qux logic // [!code focus] oneof bar { string baz = 1; string qux = 2; } } ```"},{"id":"cli/linter/rules/comment-rpc::top::0","title":"COMMENT_RPC","path":"/docs/guide/cli/linter/rules/comment-rpc","headings":[],"excerpt":"This rule checks that rpc has a comment.","content":"This rule checks that rpc has a comment."},{"id":"cli/linter/rules/comment-rpc::bad::1","title":"COMMENT_RPC","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-rpc#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-rpc::bad::2","title":"COMMENT_RPC","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-rpc#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} rpc Baz (BazRequest) returns (BazResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} rpc Baz (BazRequest) returns (BazResponse) {} } ```"},{"id":"cli/linter/rules/comment-rpc::good::3","title":"COMMENT_RPC","section":"Good","path":"/docs/guide/cli/linter/rules/comment-rpc#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-rpc::good::4","title":"COMMENT_RPC","section":"Good","path":"/docs/guide/cli/linter/rules/comment-rpc#good","headings":["Good"],"excerpt":"Good service Foo { // Bar rpc for bar logic // [!code focus] rpc Bar (BarRequest) returns (BarResponse) {} // Baz rpc for baz logic // [!code focus] rpc Baz (BazRequest) returns (BazResponse) {} } ```","content":"Good service Foo { // Bar rpc for bar logic // [!code focus] rpc Bar (BarRequest) returns (BarResponse) {} // Baz rpc for baz logic // [!code focus] rpc Baz (BazRequest) returns (BazResponse) {} } ```"},{"id":"cli/linter/rules/comment-service::top::0","title":"COMMENT_SERVICE","path":"/docs/guide/cli/linter/rules/comment-service","headings":[],"excerpt":"This rule checks that service has a comment.","content":"This rule checks that service has a comment."},{"id":"cli/linter/rules/comment-service::bad::1","title":"COMMENT_SERVICE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-service#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-service::bad::2","title":"COMMENT_SERVICE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-service#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/comment-service::good::3","title":"COMMENT_SERVICE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-service#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-service::good::4","title":"COMMENT_SERVICE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-service#good","headings":["Good"],"excerpt":"Good // Foo service for bar logic // [!code focus] service Foo { // Bar rpc for bar logic rpc Bar (BarRequest) returns (BarResponse) {} } ```","content":"Good // Foo service for bar logic // [!code focus] service Foo { // Bar rpc for bar logic rpc Bar (BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/directory-same-package::top::0","title":"DIRECTORY_SAME_PACKAGE","path":"/docs/guide/cli/linter/rules/directory-same-package","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/directory-same-package::top::1","title":"DIRECTORY_SAME_PACKAGE","path":"/docs/guide/cli/linter/rules/directory-same-package","headings":[],"excerpt":"This rule checks that all files in a given directory are in the same package.","content":"This rule checks that all files in a given directory are in the same package."},{"id":"cli/linter/rules/directory-same-package::bad::2","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: dir/foo.proto","content":"Bad ```proto // File: dir/foo.proto"},{"id":"cli/linter/rules/directory-same-package::bad::3","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad syntax = \"proto3\"; package foo;","content":"Bad syntax = \"proto3\"; package foo;"},{"id":"cli/linter/rules/directory-same-package::bad::4","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; } ```","content":"Bad message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/directory-same-package::good::5","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good ```proto // File: dir/foo/foo.proto // [!code focus]","content":"Good ```proto // File: dir/foo/foo.proto // [!code focus]"},{"id":"cli/linter/rules/directory-same-package::good::6","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good package dir.foo; // [!code focus]","content":"Good package dir.foo; // [!code focus]"},{"id":"cli/linter/rules/directory-same-package::good::7","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/enum-first-value-zero::top::0","title":"ENUM_FIRST_VALUE_ZERO","path":"/docs/guide/cli/linter/rules/enum-first-value-zero","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-first-value-zero::top::1","title":"ENUM_FIRST_VALUE_ZERO","path":"/docs/guide/cli/linter/rules/enum-first-value-zero","headings":[],"excerpt":"This rule checks that the first value of an enum is zero.","content":"This rule checks that the first value of an enum is zero."},{"id":"cli/linter/rules/enum-first-value-zero::bad::2","title":"ENUM_FIRST_VALUE_ZERO","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 1; BAZ = 2; } ```","content":"Bad enum Foo { BAR = 1; BAZ = 2; } ```"},{"id":"cli/linter/rules/enum-first-value-zero::good::3","title":"ENUM_FIRST_VALUE_ZERO","section":"Good","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::good::4","title":"ENUM_FIRST_VALUE_ZERO","section":"Good","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#good","headings":["Good"],"excerpt":"Good enum Foo { BAR = 0; // [!code focus] BAZ = 1; } ```","content":"Good enum Foo { BAR = 0; // [!code focus] BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-no-allow-alias::top::0","title":"ENUM_NO_ALLOW_ALIAS","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-no-allow-alias::top::1","title":"ENUM_NO_ALLOW_ALIAS","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias","headings":[],"excerpt":"This rule checks that the allow_alias option is not set to true in an enum.","content":"This rule checks that the allow_alias option is not set to true in an enum."},{"id":"cli/linter/rules/enum-no-allow-alias::bad::2","title":"ENUM_NO_ALLOW_ALIAS","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-no-allow-alias::bad::3","title":"ENUM_NO_ALLOW_ALIAS","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#bad","headings":["Bad"],"excerpt":"Bad enum Foo { option allow_alias = true; // [!code focus] BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { option allow_alias = true; // [!code focus] BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-no-allow-alias::good::4","title":"ENUM_NO_ALLOW_ALIAS","section":"Good","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-no-allow-alias::good::5","title":"ENUM_NO_ALLOW_ALIAS","section":"Good","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#good","headings":["Good"],"excerpt":"Good enum Foo { BAR = 0; BAZ = 1; } ```","content":"Good enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-pascal-case::top::0","title":"ENUM_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/enum-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-pascal-case::top::1","title":"ENUM_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/enum-pascal-case","headings":[],"excerpt":"This rule checks that enum names are in PascalCase.","content":"This rule checks that enum names are in PascalCase."},{"id":"cli/linter/rules/enum-pascal-case::bad::2","title":"ENUM_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-pascal-case::bad::3","title":"ENUM_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-pascal-case#bad","headings":["Bad"],"excerpt":"Bad enum foo_bar { BAR = 0; BAZ = 1; } ```","content":"Bad enum foo_bar { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-pascal-case::good::4","title":"ENUM_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-pascal-case::good::5","title":"ENUM_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-pascal-case#good","headings":["Good"],"excerpt":"Good enum FooBar { // [!code focus] BAR = 0; BAZ = 1; } ```","content":"Good enum FooBar { // [!code focus] BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-value-prefix::top::0","title":"ENUM_VALUE_PREFIX","path":"/docs/guide/cli/linter/rules/enum-value-prefix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-value-prefix::top::1","title":"ENUM_VALUE_PREFIX","path":"/docs/guide/cli/linter/rules/enum-value-prefix","headings":[],"excerpt":"This rule checks that all enum values are prefixed with the enum name.","content":"This rule checks that all enum values are prefixed with the enum name."},{"id":"cli/linter/rules/enum-value-prefix::bad::2","title":"ENUM_VALUE_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-prefix::good::3","title":"ENUM_VALUE_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-prefix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-prefix::good::4","title":"ENUM_VALUE_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-prefix#good","headings":["Good"],"excerpt":"Good enum Foo { FOO_BAR = 0; // [!code focus] } ```","content":"Good enum Foo { FOO_BAR = 0; // [!code focus] } ```"},{"id":"cli/linter/rules/enum-value-upper-snake-case::top::0","title":"ENUM_VALUE_UPPER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-value-upper-snake-case::top::1","title":"ENUM_VALUE_UPPER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case","headings":[],"excerpt":"This rule checks that enum values are in UPPER_SNAKE_CASE.","content":"This rule checks that enum values are in UPPER_SNAKE_CASE."},{"id":"cli/linter/rules/enum-value-upper-snake-case::bad::2","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-upper-snake-case::bad::3","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#bad","headings":["Bad"],"excerpt":"Bad enum Foo { barName = 0; bazName = 1; } ```","content":"Bad enum Foo { barName = 0; bazName = 1; } ```"},{"id":"cli/linter/rules/enum-value-upper-snake-case::good::4","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-upper-snake-case::good::5","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#good","headings":["Good"],"excerpt":"Good enum Foo { BAR_NAME = 0; // [!code focus] BAZ_NAME = 1; // [!code focus] } ```","content":"Good enum Foo { BAR_NAME = 0; // [!code focus] BAZ_NAME = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/enum-zero-value-suffix::top::0","title":"ENUM_ZERO_VALUE_SUFFIX","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-zero-value-suffix::top::1","title":"ENUM_ZERO_VALUE_SUFFIX","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix","headings":[],"excerpt":"This rule checks that all enum zero values are suffixed with _NONE or your custom suffix.","content":"This rule checks that all enum zero values are suffixed with _NONE or your custom suffix."},{"id":"cli/linter/rules/enum-zero-value-suffix::bad::2","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-zero-value-suffix::good::3","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-zero-value-suffix::good::4","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#good","headings":["Good"],"excerpt":"Good enum Foo { FOO_BAR_NONE = 0; // [!code focus] } ```","content":"Good enum Foo { FOO_BAR_NONE = 0; // [!code focus] } ```"},{"id":"cli/linter/rules/field-lower-snake-case::top::0","title":"FIELD_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/field-lower-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/field-lower-snake-case::top::1","title":"FIELD_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/field-lower-snake-case","headings":[],"excerpt":"This rule checks that field names of messages are in lower_snake_case.","content":"This rule checks that field names of messages are in lower_snake_case."},{"id":"cli/linter/rules/field-lower-snake-case::bad::2","title":"FIELD_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/field-lower-snake-case::bad::3","title":"FIELD_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad message Foo { string BarName = 1; } ```","content":"Bad message Foo { string BarName = 1; } ```"},{"id":"cli/linter/rules/field-lower-snake-case::good::4","title":"FIELD_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/field-lower-snake-case::good::5","title":"FIELD_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#good","headings":["Good"],"excerpt":"Good message Foo { string bar_name = 1; // [!code focus] } ```","content":"Good message Foo { string bar_name = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/file-lower-snake-case::top::0","title":"FILE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/file-lower-snake-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/file-lower-snake-case::top::1","title":"FILE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/file-lower-snake-case","headings":[],"excerpt":"This rule checks that all files are in lower_snake_case.","content":"This rule checks that all files are in lower_snake_case."},{"id":"cli/linter/rules/file-lower-snake-case::bad::2","title":"FILE_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/file-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/FooBaz.proto","content":"Bad ```proto // File: bar/FooBaz.proto"},{"id":"cli/linter/rules/file-lower-snake-case::good::3","title":"FILE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/file-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo_baz.proto // [!code focus]","content":"Good ```proto // File: bar/foo_baz.proto // [!code focus]"},{"id":"cli/linter/rules/import-no-public::top::0","title":"IMPORT_NO_PUBLIC","path":"/docs/guide/cli/linter/rules/import-no-public","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-no-public::top::1","title":"IMPORT_NO_PUBLIC","path":"/docs/guide/cli/linter/rules/import-no-public","headings":[],"excerpt":"This rule checks that no public imports are used in a proto file.","content":"This rule checks that no public imports are used in a proto file."},{"id":"cli/linter/rules/import-no-public::bad::2","title":"IMPORT_NO_PUBLIC","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-public#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-no-public::bad::3","title":"IMPORT_NO_PUBLIC","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-public#bad","headings":["Bad"],"excerpt":"Bad import public \"bar.proto\"; ```","content":"Bad import public \"bar.proto\"; ```"},{"id":"cli/linter/rules/import-no-public::good::4","title":"IMPORT_NO_PUBLIC","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-public#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-no-public::good::5","title":"IMPORT_NO_PUBLIC","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-public#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus] ```","content":"Good import \"bar.proto\"; // [!code focus] ```"},{"id":"cli/linter/rules/import-no-weak::top::0","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-no-weak::top::1","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"This rule checks that no weak imports are used in a proto file.","content":"This rule checks that no weak imports are used in a proto file."},{"id":"cli/linter/rules/import-no-weak::bad::2","title":"IMPORT_NO_WEAK","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-weak#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::3","title":"IMPORT_NO_WEAK","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-weak#bad","headings":["Bad"],"excerpt":"Bad import weak \"bar.proto\"; ```","content":"Bad import weak \"bar.proto\"; ```"},{"id":"cli/linter/rules/import-no-weak::good::4","title":"IMPORT_NO_WEAK","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-weak#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto2\";","content":"Good ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::good::5","title":"IMPORT_NO_WEAK","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-weak#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus] ```","content":"Good import \"bar.proto\"; // [!code focus] ```"},{"id":"cli/linter/rules/import-used::top::0","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"This rule checks that all imports are used in a proto file.","content":"This rule checks that all imports are used in a proto file."},{"id":"cli/linter/rules/import-used::bad::2","title":"IMPORT_USED","section":"Bad","path":"/docs/guide/cli/linter/rules/import-used#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-used::good::3","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-used::good::4","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus]","content":"Good import \"bar.proto\"; // [!code focus]"},{"id":"cli/linter/rules/import-used::good::5","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good message Foo { bar.Bar bar = 1; // [!code focus] } ```","content":"Good message Foo { bar.Bar bar = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/message-pascal-case::top::0","title":"MESSAGE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/message-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/message-pascal-case::top::1","title":"MESSAGE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/message-pascal-case","headings":[],"excerpt":"This rule checks that message names are in PascalCase.","content":"This rule checks that message names are in PascalCase."},{"id":"cli/linter/rules/message-pascal-case::bad::2","title":"MESSAGE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/message-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/message-pascal-case::bad::3","title":"MESSAGE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/message-pascal-case#bad","headings":["Bad"],"excerpt":"Bad message foo_bar { string bar_name = 1; } ```","content":"Bad message foo_bar { string bar_name = 1; } ```"},{"id":"cli/linter/rules/message-pascal-case::good::4","title":"MESSAGE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/message-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/message-pascal-case::good::5","title":"MESSAGE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/message-pascal-case#good","headings":["Good"],"excerpt":"Good message FooBar { // [!code focus] string bar_name = 1; } ```","content":"Good message FooBar { // [!code focus] string bar_name = 1; } ```"},{"id":"cli/linter/rules/oneof-lower-snake-case::top::0","title":"ONEOF_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/oneof-lower-snake-case::top::1","title":"ONEOF_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case","headings":[],"excerpt":"This rule checks that oneof names are in lower_snake_case.","content":"This rule checks that oneof names are in lower_snake_case."},{"id":"cli/linter/rules/oneof-lower-snake-case::bad::2","title":"ONEOF_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/oneof-lower-snake-case::bad::3","title":"ONEOF_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad message Foo { oneof BarName { string bar_name = 1; } } ```","content":"Bad message Foo { oneof BarName { string bar_name = 1; } } ```"},{"id":"cli/linter/rules/oneof-lower-snake-case::good::4","title":"ONEOF_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/oneof-lower-snake-case::good::5","title":"ONEOF_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#good","headings":["Good"],"excerpt":"Good message Foo { oneof bar_name { // [!code focus] string bar_name = 1; } } ```","content":"Good message Foo { oneof bar_name { // [!code focus] string bar_name = 1; } } ```"},{"id":"cli/linter/rules/package-defined::top::0","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"This rule checks that all files have a package declaration.","content":"This rule checks that all files have a package declaration."},{"id":"cli/linter/rules/package-defined::bad::2","title":"PACKAGE_DEFINED","section":"Bad","path":"/docs/guide/cli/linter/rules/package-defined#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-defined::bad::3","title":"PACKAGE_DEFINED","section":"Bad","path":"/docs/guide/cli/linter/rules/package-defined#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-defined::good::4","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-defined::good::5","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good package foo; // [!code focus]","content":"Good package foo; // [!code focus]"},{"id":"cli/linter/rules/package-defined::good::6","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/package-directory-match::top::0","title":"PACKAGE_DIRECTORY_MATCH","path":"/docs/guide/cli/linter/rules/package-directory-match","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-directory-match::top::1","title":"PACKAGE_DIRECTORY_MATCH","path":"/docs/guide/cli/linter/rules/package-directory-match","headings":[],"excerpt":"This rule checks that all files are in a directory that matches their package name.","content":"This rule checks that all files are in a directory that matches their package name."},{"id":"cli/linter/rules/package-directory-match::bad::2","title":"PACKAGE_DIRECTORY_MATCH","section":"Bad","path":"/docs/guide/cli/linter/rules/package-directory-match#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto","content":"Bad ```proto // File: bar/foo.proto"},{"id":"cli/linter/rules/package-directory-match::bad::3","title":"PACKAGE_DIRECTORY_MATCH","section":"Bad","path":"/docs/guide/cli/linter/rules/package-directory-match#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-directory-match::good::4","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto // [!code focus]","content":"Good ```proto // File: bar/foo.proto // [!code focus]"},{"id":"cli/linter/rules/package-directory-match::good::5","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good package bar; // [!code focus]","content":"Good package bar; // [!code focus]"},{"id":"cli/linter/rules/package-directory-match::good::6","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/package-lower-snake-case::top::0","title":"PACKAGE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/package-lower-snake-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-lower-snake-case::top::1","title":"PACKAGE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/package-lower-snake-case","headings":[],"excerpt":"This rule checks that package names are in lower_snake_case.","content":"This rule checks that package names are in lower_snake_case."},{"id":"cli/linter/rules/package-lower-snake-case::bad::2","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto syntax = \"proto3\";","content":"Bad ```proto // File: bar/foo.proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-lower-snake-case::good::3","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto syntax = \"proto3\";","content":"Good ```proto // File: bar/foo.proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-lower-snake-case::good::4","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#good","headings":["Good"],"excerpt":"Good package foo_bar; // [!code focus] ```","content":"Good package foo_bar; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::top::0","title":"PACKAGE_SAME_CSHARP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-csharp-namespace::top::1","title":"PACKAGE_SAME_CSHARP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace","headings":[],"excerpt":"This rule checks that all files with a given package are in the same C# namespace.","content":"This rule checks that all files with a given package are in the same C# namespace."},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::2","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::3","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad option csharp_namespace = \"Foo.Bar\"; ```","content":"Bad option csharp_namespace = \"Foo.Bar\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::4","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::5","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad option csharp_namespace = \"Foo.Baz\"; ```","content":"Bad option csharp_namespace = \"Foo.Baz\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::6","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::7","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good option csharp_namespace = \"Foo.Bar\"; ```","content":"Good option csharp_namespace = \"Foo.Bar\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::8","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-directory::top::0","title":"PACKAGE_SAME_DIRECTORY","path":"/docs/guide/cli/linter/rules/package-same-directory","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-directory::top::1","title":"PACKAGE_SAME_DIRECTORY","path":"/docs/guide/cli/linter/rules/package-same-directory","headings":[],"excerpt":"This rule checks that all files with a given package are in the same directory.","content":"This rule checks that all files with a given package are in the same directory."},{"id":"cli/linter/rules/package-same-directory::bad::2","title":"PACKAGE_SAME_DIRECTORY","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-directory#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto","content":"Bad ```proto // File: bar/foo.proto"},{"id":"cli/linter/rules/package-same-directory::bad::3","title":"PACKAGE_SAME_DIRECTORY","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-directory#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-same-directory::good::4","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto // [!code focus]","content":"Good ```proto // File: bar/foo.proto // [!code focus]"},{"id":"cli/linter/rules/package-same-directory::good::5","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good package bar; // [!code focus]","content":"Good package bar; // [!code focus]"},{"id":"cli/linter/rules/package-same-directory::good::6","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; }","content":"Good message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-same-go-package::top::0","title":"PACKAGE_SAME_GO_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-go-package","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-go-package::top::1","title":"PACKAGE_SAME_GO_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-go-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Go package.","content":"This rule checks that all files with a given package are in the same Go package."},{"id":"cli/linter/rules/package-same-go-package::bad::2","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-go-package::bad::3","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad option go_package = \"example.com/foo/bar\";","content":"Bad option go_package = \"example.com/foo/bar\";"},{"id":"cli/linter/rules/package-same-go-package::bad::4","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-go-package::bad::5","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad option go_package = \"example.com/foo/baz\";","content":"Bad option go_package = \"example.com/foo/baz\";"},{"id":"cli/linter/rules/package-same-go-package::good::6","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-go-package::good::7","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```","content":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-go-package::good::8","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-go-package::good::9","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```","content":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::0","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","content":"PACKAGE_SAME_JAVA_MULTIPLE_FILES"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::1","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::2","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Java package.","content":"This rule checks that all files with a given package are in the same Java package."},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::3","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::4","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.foo\"; ```","content":"Bad option java_package = \"com.example.foo\"; ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::5","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.bar\"; ```","content":"Bad option java_package = \"com.example.bar\"; ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::6","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::7","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::8","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::9","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-package::top::0","title":"PACKAGE_SAME_JAVA_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-java-package","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-java-package::top::1","title":"PACKAGE_SAME_JAVA_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-java-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Java package.","content":"This rule checks that all files with a given package are in the same Java package."},{"id":"cli/linter/rules/package-same-java-package::bad::2","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-package::bad::3","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.foo\"; ```","content":"Bad option java_package = \"com.example.foo\"; ```"},{"id":"cli/linter/rules/package-same-java-package::bad::4","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-package::bad::5","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.bar\"; ```","content":"Bad option java_package = \"com.example.bar\"; ```"},{"id":"cli/linter/rules/package-same-java-package::good::6","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-package::good::7","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-package::good::8","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-package::good::9","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-php-namespace::top::0","title":"PACKAGE_SAME_PHP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-php-namespace","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-php-namespace::top::1","title":"PACKAGE_SAME_PHP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-php-namespace","headings":[],"excerpt":"This rule checks that all files with a given package are in the same PHP namespace.","content":"This rule checks that all files with a given package are in the same PHP namespace."},{"id":"cli/linter/rules/package-same-php-namespace::bad::2","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-php-namespace::bad::3","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad option php_namespace = \"Foo\\\\Bar\";","content":"Bad option php_namespace = \"Foo\\\\Bar\";"},{"id":"cli/linter/rules/package-same-php-namespace::bad::4","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-php-namespace::bad::5","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad option php_namespace = \"Foo\\\\Baz\"; ```","content":"Bad option php_namespace = \"Foo\\\\Baz\"; ```"},{"id":"cli/linter/rules/package-same-php-namespace::good::6","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-php-namespace::good::7","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```","content":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-php-namespace::good::8","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-php-namespace::good::9","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```","content":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-ruby-package::top::0","title":"PACKAGE_SAME_RUBY_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-ruby-package","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-ruby-package::top::1","title":"PACKAGE_SAME_RUBY_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-ruby-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Ruby package.","content":"This rule checks that all files with a given package are in the same Ruby package."},{"id":"cli/linter/rules/package-same-ruby-package::bad::2","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-ruby-package::bad::3","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad option ruby_package = \"Foo\"; ```","content":"Bad option ruby_package = \"Foo\"; ```"},{"id":"cli/linter/rules/package-same-ruby-package::bad::4","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-ruby-package::bad::5","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad option ruby_package = \"Bar\"; ```","content":"Bad option ruby_package = \"Bar\"; ```"},{"id":"cli/linter/rules/package-same-ruby-package::good::6","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-ruby-package::good::7","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good option ruby_package = \"Foo\"; // [!code focus] ```","content":"Good option ruby_package = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-ruby-package::good::8","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-ruby-package::good::9","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good option ruby_package = \"Foo\"; // [!code focus] ```","content":"Good option ruby_package = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-swift-prefix::top::0","title":"PACKAGE_SAME_SWIFT_PREFIX","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-swift-prefix::top::1","title":"PACKAGE_SAME_SWIFT_PREFIX","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Swift prefix.","content":"This rule checks that all files with a given package are in the same Swift prefix."},{"id":"cli/linter/rules/package-same-swift-prefix::bad::2","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::3","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad option swift_prefix = \"Foo\"; ```","content":"Bad option swift_prefix = \"Foo\"; ```"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::4","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::5","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad option swift_prefix = \"Bar\"; ```","content":"Bad option swift_prefix = \"Bar\"; ```"},{"id":"cli/linter/rules/package-same-swift-prefix::good::6","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::good::7","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good option swift_prefix = \"Foo\"; // [!code focus] ```","content":"Good option swift_prefix = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-swift-prefix::good::8","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::good::9","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good option swift_prefix = \"Foo\"; // [!code focus] ```","content":"Good option swift_prefix = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-version-suffix::top::0","title":"PACKAGE_VERSION_SUFFIX","path":"/docs/guide/cli/linter/rules/package-version-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-version-suffix::top::1","title":"PACKAGE_VERSION_SUFFIX","path":"/docs/guide/cli/linter/rules/package-version-suffix","headings":[],"excerpt":"This rule checks that the package version suffix is _vX where X is a number of version.","content":"This rule checks that the package version suffix is _vX where X is a number of version."},{"id":"cli/linter/rules/package-version-suffix::bad::2","title":"PACKAGE_VERSION_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-version-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-version-suffix::good::3","title":"PACKAGE_VERSION_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-version-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-version-suffix::good::4","title":"PACKAGE_VERSION_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-version-suffix#good","headings":["Good"],"excerpt":"Good package foo.v1; // [!code focus] ```","content":"Good package foo.v1; // [!code focus] ```"},{"id":"cli/linter/rules/rpc-no-client-streaming::top::0","title":"RPC_NO_CLIENT_STREAMING","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming","headings":[],"excerpt":"This rule checks that rpc has no client streaming.","content":"This rule checks that rpc has no client streaming."},{"id":"cli/linter/rules/rpc-no-client-streaming::bad::1","title":"RPC_NO_CLIENT_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-client-streaming::bad::2","title":"RPC_NO_CLIENT_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (stream BarRequest) returns (BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (stream BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-no-client-streaming::good::3","title":"RPC_NO_CLIENT_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-client-streaming::good::4","title":"RPC_NO_CLIENT_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#good","headings":["Good"],"excerpt":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-no-server-streaming::top::0","title":"RPC_NO_SERVER_STREAMING","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming","headings":[],"excerpt":"This rule checks that rpc has no server streaming.","content":"This rule checks that rpc has no server streaming."},{"id":"cli/linter/rules/rpc-no-server-streaming::bad::1","title":"RPC_NO_SERVER_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-server-streaming::bad::2","title":"RPC_NO_SERVER_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (stream BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (stream BarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-no-server-streaming::good::3","title":"RPC_NO_SERVER_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-server-streaming::good::4","title":"RPC_NO_SERVER_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#good","headings":["Good"],"excerpt":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-pascal-case::top::0","title":"RPC_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/rpc-pascal-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-pascal-case::top::1","title":"RPC_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/rpc-pascal-case","headings":[],"excerpt":"This rule checks that all RPC names are in PascalCase.","content":"This rule checks that all RPC names are in PascalCase."},{"id":"cli/linter/rules/rpc-pascal-case::bad::2","title":"RPC_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-pascal-case::bad::3","title":"RPC_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#bad","headings":["Bad"],"excerpt":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-pascal-case::good::4","title":"RPC_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-pascal-case::good::5","title":"RPC_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#good","headings":["Good"],"excerpt":"Good service FooBar { rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] } ```","content":"Good service FooBar { rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-request-response-unique::top::0","title":"RPC_REQUEST_RESPONSE_UNIQUE","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-request-response-unique::top::1","title":"RPC_REQUEST_RESPONSE_UNIQUE","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique","headings":[],"excerpt":"This rule checks that all RPC request and response messages are unique.","content":"This rule checks that all RPC request and response messages are unique."},{"id":"cli/linter/rules/rpc-request-response-unique::bad::2","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-response-unique::bad::3","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} rpc GetBar (FooRequest) returns (FooResponse) {} } ```","content":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} rpc GetBar (FooRequest) returns (FooResponse) {} } ```"},{"id":"cli/linter/rules/rpc-request-response-unique::good::4","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-response-unique::good::5","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-request-standard-name::top::0","title":"RPC_REQUEST_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-request-standard-name::top::1","title":"RPC_REQUEST_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name","headings":[],"excerpt":"This rule checks that all RPC request messages are named MethodRequest.","content":"This rule checks that all RPC request messages are named MethodRequest."},{"id":"cli/linter/rules/rpc-request-standard-name::bad::2","title":"RPC_REQUEST_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-standard-name::bad::3","title":"RPC_REQUEST_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} } ```","content":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} } ```"},{"id":"cli/linter/rules/rpc-request-standard-name::good::4","title":"RPC_REQUEST_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-standard-name::good::5","title":"RPC_REQUEST_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-response-standard-name::top::0","title":"RPC_RESPONSE_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-response-standard-name::top::1","title":"RPC_RESPONSE_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name","headings":[],"excerpt":"This rule checks that all RPC response messages are named MethodResponse.","content":"This rule checks that all RPC response messages are named MethodResponse."},{"id":"cli/linter/rules/rpc-response-standard-name::bad::2","title":"RPC_RESPONSE_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-response-standard-name::bad::3","title":"RPC_RESPONSE_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (GetFooRequest) returns (Foo) {} } ```","content":"Bad service Foo { rpc GetFoo (GetFooRequest) returns (Foo) {} } ```"},{"id":"cli/linter/rules/rpc-response-standard-name::good::4","title":"RPC_RESPONSE_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-response-standard-name::good::5","title":"RPC_RESPONSE_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/service-pascal-case::top::0","title":"SERVICE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/service-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/service-pascal-case::top::1","title":"SERVICE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/service-pascal-case","headings":[],"excerpt":"This rule checks that all service names are in PascalCase.","content":"This rule checks that all service names are in PascalCase."},{"id":"cli/linter/rules/service-pascal-case::bad::2","title":"SERVICE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/service-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-pascal-case::bad::3","title":"SERVICE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/service-pascal-case#bad","headings":["Bad"],"excerpt":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/service-pascal-case::good::4","title":"SERVICE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/service-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-pascal-case::good::5","title":"SERVICE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/service-pascal-case#good","headings":["Good"],"excerpt":"Good service FooBar { // [!code focus] rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Good service FooBar { // [!code focus] rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/service-suffix::top::0","title":"SERVICE_SUFFIX","path":"/docs/guide/cli/linter/rules/service-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/service-suffix::top::1","title":"SERVICE_SUFFIX","path":"/docs/guide/cli/linter/rules/service-suffix","headings":[],"excerpt":"This rule checks that all services are suffixed with Service or your custom suffix.","content":"This rule checks that all services are suffixed with Service or your custom suffix."},{"id":"cli/linter/rules/service-suffix::bad::2","title":"SERVICE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/service-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-suffix::bad::3","title":"SERVICE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/service-suffix#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar(BarRequest) returns (BarResponse); } ```","content":"Bad service Foo { rpc Bar(BarRequest) returns (BarResponse); } ```"},{"id":"cli/linter/rules/service-suffix::good::4","title":"SERVICE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/service-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-suffix::good::5","title":"SERVICE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/service-suffix#good","headings":["Good"],"excerpt":"Good service FooService { // [!code focus] rpc Bar(BarRequest) returns (BarResponse); } ```","content":"Good service FooService { // [!code focus] rpc Bar(BarRequest) returns (BarResponse); } ```"},{"id":"cli/package-manager/easyp-vs-buf::top::0","title":"EasyP vs Buf Package Management","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP vs Buf Package Management","content":"EasyP vs Buf Package Management"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP vs Buf Package Management","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"This document provides a comprehensive comparison between EasyP's decentralized package management approach and Buf's centralized Buf Schema Registry (BSR) model, helping you understand the key differences and choose the","content":"This document provides a comprehensive comparison between EasyP's decentralized package management approach and Buf's centralized Buf Schema Registry (BSR) model, helping you understand the key differences and choose the right solution for your needs."},{"id":"cli/package-manager/easyp-vs-buf::easyp-decentralized-git-based-approach::2","title":"EasyP vs Buf Package Management","section":"EasyP: Decentralized Git-Based Approach","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-decentralized-git-based-approach","headings":["EasyP: Decentralized Git-Based Approach"],"excerpt":"EasyP: Decentralized Git-Based Approach","content":"EasyP: Decentralized Git-Based Approach"},{"id":"cli/package-manager/easyp-vs-buf::buf-centralized-registry-approach::3","title":"EasyP vs Buf Package Management","section":"Buf: Centralized Registry Approach","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-centralized-registry-approach","headings":["Buf: Centralized Registry Approach"],"excerpt":"Buf: Centralized Registry Approach","content":"Buf: Centralized Registry Approach"},{"id":"cli/package-manager/easyp-vs-buf::key-differences-summary::4","title":"EasyP vs Buf Package Management","section":"Key Differences Summary","path":"/docs/guide/cli/package-manager/easyp-vs-buf#key-differences-summary","headings":["Key Differences Summary"],"excerpt":"Key Differences Summary Aspect EasyP Buf -------- ------- ----- **Architecture** Decentralized (Git-based) Centralized (BSR registry) **Dependency Source** Any Git repository Buf Schema Registry only **Single Point of Fa","content":"Key Differences Summary Aspect EasyP Buf -------- ------- ----- **Architecture** Decentralized (Git-based) Centralized (BSR registry) **Dependency Source** Any Git repository Buf Schema Registry only **Single Point of Failure** No Yes (buf.build) **Enterprise Deployment** Fully air-gapped support Requires BSR access or private BSR **Authentication** Git credentials (SSH/HTTPS) Buf tokens + Git credentials **Vendor Lock-in** None Buf ecosystem **Private Repositories** Native Git support Must publish to BSR first **Offline Support** Full (via vendoring) Limited (cached modules only) **Cost** Free (uses existing Git) Free tier + paid plans **Setup Complexity** Minimal Moderate (BSR setup)"},{"id":"cli/package-manager/easyp-vs-buf::1-dependency-management-philosophy::5","title":"EasyP vs Buf Package Management","section":"1. Dependency Management Philosophy","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1-dependency-management-philosophy","headings":["1. Dependency Management Philosophy"],"excerpt":"Dependency Management Philosophy","content":"Dependency Management Philosophy"},{"id":"cli/package-manager/easyp-vs-buf::easyp-any-git-repository-is-a-package::6","title":"EasyP vs Buf Package Management","section":"EasyP: \"Any Git Repository is a Package\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-any-git-repository-is-a-package","headings":["EasyP: \"Any Git Repository is a Package\""],"excerpt":"EasyP: \"Any Git Repository is a Package\"","content":"EasyP: \"Any Git Repository is a Package\""},{"id":"cli/package-manager/easyp-vs-buf::easyp-any-git-repository-is-a-package::7","title":"EasyP vs Buf Package Management","section":"EasyP: \"Any Git Repository is a Package\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-any-git-repository-is-a-package","headings":["EasyP: \"Any Git Repository is a Package\""],"excerpt":"EasyP: \"Any Git Repository is a Package\" **Advantages:** ✅ Use any existing Git repository immediately ✅ No need to \"publish\" to a separate registry ✅ Version control is the source of truth ✅ Works with private Git serve","content":"EasyP: \"Any Git Repository is a Package\" **Advantages:** ✅ Use any existing Git repository immediately ✅ No need to \"publish\" to a separate registry ✅ Version control is the source of truth ✅ Works with private Git servers out-of-the-box"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::8","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\"","content":"Buf: \"Registry-First Approach\""},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::9","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\" **Advantages:** ✅ Curated, high-quality modules ✅ Rich metadata and documentation ✅ Dependency graph visualization ✅ Semantic versioning enforcement","content":"Buf: \"Registry-First Approach\" **Advantages:** ✅ Curated, high-quality modules ✅ Rich metadata and documentation ✅ Dependency graph visualization ✅ Semantic versioning enforcement"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::10","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\" **Limitations:** ❌ Must publish to BSR before use ❌ Requires BSR account and authentication ❌ Cannot reference arbitrary Git repositories directly","content":"Buf: \"Registry-First Approach\" **Limitations:** ❌ Must publish to BSR before use ❌ Requires BSR account and authentication ❌ Cannot reference arbitrary Git repositories directly"},{"id":"cli/package-manager/easyp-vs-buf::2-enterprise-and-air-gapped-environments::11","title":"EasyP vs Buf Package Management","section":"2. Enterprise and Air-Gapped Environments","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-enterprise-and-air-gapped-environments","headings":["2. Enterprise and Air-Gapped Environments"],"excerpt":"Enterprise and Air-Gapped Environments","content":"Enterprise and Air-Gapped Environments"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::12","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support **Scenario**: Large enterprise with strict network policies","content":"EasyP: Full Air-Gap Support **Scenario**: Large enterprise with strict network policies"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::13","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support ```bash Initial setup (with internet) easyp mod download # Downloads to ~/.easyp/ easyp mod vendor # Creates easyp_vendor/","content":"EasyP: Full Air-Gap Support ```bash Initial setup (with internet) easyp mod download # Downloads to ~/.easyp/ easyp mod vendor # Creates easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::14","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support Transfer to air-gapped environment tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... transfer archive ...","content":"EasyP: Full Air-Gap Support Transfer to air-gapped environment tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... transfer archive ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::15","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support Air-gapped environment (no internet) tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Works offline ```","content":"EasyP: Full Air-Gap Support Air-gapped environment (no internet) tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Works offline ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::16","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support **Benefits:** ✅ Complete independence from external services ✅ No need for internal registry infrastructure ✅ Uses existing Git infrastructure ✅ Simple file-based distribution","content":"EasyP: Full Air-Gap Support **Benefits:** ✅ Complete independence from external services ✅ No need for internal registry infrastructure ✅ Uses existing Git infrastructure ✅ Simple file-based distribution"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::17","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure **Scenario**: Same enterprise setup","content":"Buf: Requires BSR Infrastructure **Scenario**: Same enterprise setup"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::18","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure ```bash Option 1: Use buf.build (requires internet) buf mod download # Must reach buf.build","content":"Buf: Requires BSR Infrastructure ```bash Option 1: Use buf.build (requires internet) buf mod download # Must reach buf.build"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::19","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure Option 2: Set up private BSR (complex) Deploy BSR server infrastructure Migrate all modules to private BSR Configure authentication and access Maintain registry server ```","content":"Buf: Requires BSR Infrastructure Option 2: Set up private BSR (complex) Deploy BSR server infrastructure Migrate all modules to private BSR Configure authentication and access Maintain registry server ```"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::20","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure **Challenges:** ❌ Requires constant internet access OR expensive private BSR ❌ Complex infrastructure for private deployments ❌ All modules must be re-published to private registry ❌ Addi","content":"Buf: Requires BSR Infrastructure **Challenges:** ❌ Requires constant internet access OR expensive private BSR ❌ Complex infrastructure for private deployments ❌ All modules must be re-published to private registry ❌ Additional operational overhead"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::21","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control ```yaml Full control over dependency sources deps: # Public repository - your choice of version - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Direct Control ```yaml Full control over dependency sources deps: # Public repository - your choice of version - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::22","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control Internal repository - complete control - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Direct Control Internal repository - complete control - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::23","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control Specific commit for security fix - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Direct Control Specific commit for security fix - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::24","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control **Security advantages:** ✅ **No intermediary** - direct from source repository ✅ **Audit trail** - Git commit history is the source of truth ✅ **Cannot be \"banned\"** - no external party can revoke a","content":"EasyP: Direct Control **Security advantages:** ✅ **No intermediary** - direct from source repository ✅ **Audit trail** - Git commit history is the source of truth ✅ **Cannot be \"banned\"** - no external party can revoke access ✅ **Custom validation** - implement your own security scanning ✅ **Fork protection** - easily fork and maintain dependencies"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-dependency::25","title":"EasyP vs Buf Package Management","section":"Buf: Registry Dependency","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-dependency","headings":["Buf: Registry Dependency"],"excerpt":"Buf: Registry Dependency **Security considerations:** ⚠️ **Intermediary risk** - BSR controls what's available ⚠️ **Account suspension** - Could lose access to dependencies ⚠️ **Module removal** - Modules can be deleted ","content":"Buf: Registry Dependency **Security considerations:** ⚠️ **Intermediary risk** - BSR controls what's available ⚠️ **Account suspension** - Could lose access to dependencies ⚠️ **Module removal** - Modules can be deleted from registry ⚠️ **Update policies** - BSR may force updates or deprecations ⚠️ **Third-party trust** - Must trust Buf's security practices"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::26","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **EasyP Approach:**","content":"Scenario 1: Startup with Public Dependencies **EasyP Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::27","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **Buf Approach:**","content":"Scenario 1: Startup with Public Dependencies **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::28","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **Winner**: Tie - both work well for public dependencies","content":"Scenario 1: Startup with Public Dependencies **Winner**: Tie - both work well for public dependencies"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::29","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **EasyP Approach:** ```yaml deps: # Public - github.com/googleapis/googleapis@v1.2.3","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **EasyP Approach:** ```yaml deps: # Public - github.com/googleapis/googleapis@v1.2.3"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::30","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies Private (existing Git repos) - github.com/mycompany/auth-protos@v2.0.0 - gitlab.enterprise.com/platform/shared-types@v1.5.1 ```","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies Private (existing Git repos) - github.com/mycompany/auth-protos@v2.0.0 - gitlab.enterprise.com/platform/shared-types@v1.5.1 ```"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::31","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Buf Approach:**","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::32","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Winner**: **EasyP** - no additional setup for private repos","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Winner**: **EasyP** - no additional setup for private repos"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::33","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **EasyP Approach:** ```bash Internet-connected environment easyp mod vendor","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **EasyP Approach:** ```bash Internet-connected environment easyp mod vendor"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::34","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) Transfer to classified environment Works immediately without any external dependencies ```","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) Transfer to classified environment Works immediately without any external dependencies ```"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::35","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Buf Approach:**","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::36","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Winner**: **EasyP** - significantly simpler air-gap deployment","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Winner**: **EasyP** - significantly simpler air-gap deployment"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::37","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **EasyP Approach:** ✅ **Direct audit trail**: Git commits show exact changes ✅ **Compliance-friendly**: No external dependencies in production ✅ **Reproducible**: Lock files pin exact ","content":"Scenario 4: Compliance and Auditing **EasyP Approach:** ✅ **Direct audit trail**: Git commits show exact changes ✅ **Compliance-friendly**: No external dependencies in production ✅ **Reproducible**: Lock files pin exact Git commits ✅ **Vulnerability management**: Direct control over security updates"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::38","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **Buf Approach:** ⚠️ **Registry dependency**: Must audit BSR's security practices ⚠️ **Third-party risk**: BSR is part of your compliance scope ⚠️ **Limited control**: Cannot control w","content":"Scenario 4: Compliance and Auditing **Buf Approach:** ⚠️ **Registry dependency**: Must audit BSR's security practices ⚠️ **Third-party risk**: BSR is part of your compliance scope ⚠️ **Limited control**: Cannot control when modules are updated/removed ⚠️ **Audit complexity**: Must trace registry → Git → actual code"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::39","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **Winner**: **EasyP** - cleaner compliance story","content":"Scenario 4: Compliance and Auditing **Winner**: **EasyP** - cleaner compliance story"},{"id":"cli/package-manager/easyp-vs-buf::easyp-zero-additional-infrastructure::40","title":"EasyP vs Buf Package Management","section":"EasyP: Zero Additional Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-zero-additional-infrastructure","headings":["EasyP: Zero Additional Infrastructure"],"excerpt":"EasyP: Zero Additional Infrastructure **Costs:** ✅ **$0** - Uses existing Git infrastructure ✅ **No additional servers** to maintain ✅ **No licensing fees** for registry software ✅ **Scales with Git** - proven enterprise","content":"EasyP: Zero Additional Infrastructure **Costs:** ✅ **$0** - Uses existing Git infrastructure ✅ **No additional servers** to maintain ✅ **No licensing fees** for registry software ✅ **Scales with Git** - proven enterprise scalability"},{"id":"cli/package-manager/easyp-vs-buf::easyp-zero-additional-infrastructure::41","title":"EasyP vs Buf Package Management","section":"EasyP: Zero Additional Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-zero-additional-infrastructure","headings":["EasyP: Zero Additional Infrastructure"],"excerpt":"EasyP: Zero Additional Infrastructure **Infrastructure:** Uses existing Git repositories (GitHub, GitLab, etc.) Leverages existing authentication systems No additional backup/disaster recovery needed","content":"EasyP: Zero Additional Infrastructure **Infrastructure:** Uses existing Git repositories (GitHub, GitLab, etc.) Leverages existing authentication systems No additional backup/disaster recovery needed"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-infrastructure-costs::42","title":"EasyP vs Buf Package Management","section":"Buf: Registry Infrastructure Costs","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-infrastructure-costs","headings":["Buf: Registry Infrastructure Costs"],"excerpt":"Buf: Registry Infrastructure Costs **BSR Hosted (buf.build):** ✅ Free tier available ❌ Paid plans for private modules and teams ❌ Subject to external pricing changes ❌ Data locality concerns for some enterprises","content":"Buf: Registry Infrastructure Costs **BSR Hosted (buf.build):** ✅ Free tier available ❌ Paid plans for private modules and teams ❌ Subject to external pricing changes ❌ Data locality concerns for some enterprises"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-infrastructure-costs::43","title":"EasyP vs Buf Package Management","section":"Buf: Registry Infrastructure Costs","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-infrastructure-costs","headings":["Buf: Registry Infrastructure Costs"],"excerpt":"Buf: Registry Infrastructure Costs **Private BSR Deployment:** ❌ Significant infrastructure costs (servers, databases, load balancers) ❌ Operational overhead (monitoring, updates, backups) ❌ Licensing costs for enterpris","content":"Buf: Registry Infrastructure Costs **Private BSR Deployment:** ❌ Significant infrastructure costs (servers, databases, load balancers) ❌ Operational overhead (monitoring, updates, backups) ❌ Licensing costs for enterprise features ❌ Additional disaster recovery planning"},{"id":"cli/package-manager/easyp-vs-buf::easyp-no-lock-in::44","title":"EasyP vs Buf Package Management","section":"EasyP: No Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-no-lock-in","headings":["EasyP: No Lock-in"],"excerpt":"EasyP: No Lock-in **Migration FROM EasyP:**","content":"EasyP: No Lock-in **Migration FROM EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::easyp-no-lock-in::45","title":"EasyP vs Buf Package Management","section":"EasyP: No Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-no-lock-in","headings":["EasyP: No Lock-in"],"excerpt":"EasyP: No Lock-in **Migration TO EasyP:**","content":"EasyP: No Lock-in **Migration TO EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-potential-lock-in::46","title":"EasyP vs Buf Package Management","section":"Buf: Potential Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-potential-lock-in","headings":["Buf: Potential Lock-in"],"excerpt":"Buf: Potential Lock-in **Migration FROM Buf:** ❌ Must identify original Git repositories for each BSR module ❌ BSR-specific module names don't translate directly ❌ May lose version history and metadata ❌ Complex if heavi","content":"Buf: Potential Lock-in **Migration FROM Buf:** ❌ Must identify original Git repositories for each BSR module ❌ BSR-specific module names don't translate directly ❌ May lose version history and metadata ❌ Complex if heavily integrated with BSR ecosystem"},{"id":"cli/package-manager/easyp-vs-buf::buf-potential-lock-in::47","title":"EasyP vs Buf Package Management","section":"Buf: Potential Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-potential-lock-in","headings":["Buf: Potential Lock-in"],"excerpt":"Buf: Potential Lock-in **Migration TO Buf:** ❌ Must publish all dependencies to BSR first ❌ Cannot reference Git repositories directly ❌ Must adopt BSR workflow and tooling","content":"Buf: Potential Lock-in **Migration TO Buf:** ❌ Must publish all dependencies to BSR first ❌ Cannot reference Git repositories directly ❌ Must adopt BSR workflow and tooling"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::48","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Enterprise/Air-gapped environments** Need to work without external dependencies Strict compliance requirements Air-gapped or classified networks","content":"Choose EasyP When: ✅ **Enterprise/Air-gapped environments** Need to work without external dependencies Strict compliance requirements Air-gapped or classified networks"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::49","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Security-first organizations** Want direct control over dependency sources Need to audit entire supply chain Concerned about third-party service risks","content":"Choose EasyP When: ✅ **Security-first organizations** Want direct control over dependency sources Need to audit entire supply chain Concerned about third-party service risks"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::50","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Existing Git-heavy workflows** Team already comfortable with Git Extensive private repository usage Want to minimize new tools/infrastructure","content":"Choose EasyP When: ✅ **Existing Git-heavy workflows** Team already comfortable with Git Extensive private repository usage Want to minimize new tools/infrastructure"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::51","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Cost-sensitive projects** Want to avoid additional licensing costs Don't want infrastructure overhead Need predictable, zero-cost scaling","content":"Choose EasyP When: ✅ **Cost-sensitive projects** Want to avoid additional licensing costs Don't want infrastructure overhead Need predictable, zero-cost scaling"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::52","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Mixed public/private dependencies** Heavy use of internal Git repositories Don't want to republish existing repos Need flexibility in dependency sources","content":"Choose EasyP When: ✅ **Mixed public/private dependencies** Heavy use of internal Git repositories Don't want to republish existing repos Need flexibility in dependency sources"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::53","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Heavy BSR ecosystem usage** Already invested in Buf tooling (lint, breaking changes, generation) Want curated, high-quality modules Benefit from BSR's rich metadata and docs","content":"Choose Buf When: ✅ **Heavy BSR ecosystem usage** Already invested in Buf tooling (lint, breaking changes, generation) Want curated, high-quality modules Benefit from BSR's rich metadata and docs"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::54","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Collaborative development** Need dependency graph visualization Want centralized module discovery Benefit from BSR's collaboration features","content":"Choose Buf When: ✅ **Collaborative development** Need dependency graph visualization Want centralized module discovery Benefit from BSR's collaboration features"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::55","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Simple public-only dependencies** Primarily use well-known public modules Don't mind BSR dependency Value the curated module experience","content":"Choose Buf When: ✅ **Simple public-only dependencies** Primarily use well-known public modules Don't mind BSR dependency Value the curated module experience"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::56","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Team new to protobuf** Benefit from BSR's documentation and examples Want guided module discovery Prefer opinionated, structured approach","content":"Choose Buf When: ✅ **Team new to protobuf** Benefit from BSR's documentation and examples Want guided module discovery Prefer opinionated, structured approach"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::57","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP **Identify source repositories** for each BSR module **Map BSR modules** to Git repository references **Update configuration** to use Git URLs **Test compatibility** and resolve any issues","content":"Migrating from Buf to EasyP **Identify source repositories** for each BSR module **Map BSR modules** to Git repository references **Update configuration** to use Git URLs **Test compatibility** and resolve any issues"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::58","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP Example migration: ```yaml Before (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Migrating from Buf to EasyP Example migration: ```yaml Before (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::59","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP After (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Migrating from Buf to EasyP After (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-easyp-to-buf::60","title":"EasyP vs Buf Package Management","section":"Migrating from EasyP to Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-easyp-to-buf","headings":["Migrating from EasyP to Buf"],"excerpt":"Migrating from EasyP to Buf **Publish modules** to BSR (if not already available) **Create BSR account** and configure authentication **Update configuration** to reference BSR modules **Adopt BSR workflow** (push, pull, ","content":"Migrating from EasyP to Buf **Publish modules** to BSR (if not already available) **Create BSR account** and configure authentication **Update configuration** to reference BSR modules **Adopt BSR workflow** (push, pull, etc.)"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::61","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion Both EasyP and Buf offer valid approaches to protobuf dependency management, but they serve different needs:","content":"Conclusion Both EasyP and Buf offer valid approaches to protobuf dependency management, but they serve different needs:"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::62","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion **EasyP excels in:** Enterprise and air-gapped environments Security-conscious organizations Cost-sensitive projects Direct Git repository usage Zero-infrastructure deployments","content":"Conclusion **EasyP excels in:** Enterprise and air-gapped environments Security-conscious organizations Cost-sensitive projects Direct Git repository usage Zero-infrastructure deployments"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::63","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion **Buf excels in:** Collaborative, open-source focused teams Organizations wanting curated, high-quality modules Teams new to protobuf ecosystem Projects heavily using BSR features","content":"Conclusion **Buf excels in:** Collaborative, open-source focused teams Organizations wanting curated, high-quality modules Teams new to protobuf ecosystem Projects heavily using BSR features"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::64","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion The choice between EasyP and Buf often comes down to your organization's priorities around **control vs. convenience**, **security vs. collaboration features**, and **infrastructure costs vs. managed services*","content":"Conclusion The choice between EasyP and Buf often comes down to your organization's priorities around **control vs. convenience**, **security vs. collaboration features**, and **infrastructure costs vs. managed services**."},{"id":"cli/package-manager/easyp-vs-buf::conclusion::65","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion For many enterprise environments, EasyP's decentralized, Git-native approach provides the security, control, and cost-effectiveness needed for production protobuf workflows, while Buf's centralized registry ex","content":"Conclusion For many enterprise environments, EasyP's decentralized, Git-native approach provides the security, control, and cost-effectiveness needed for production protobuf workflows, while Buf's centralized registry excels in collaborative, open-source focused development environments."},{"id":"cli/package-manager/package-manager::top::0","title":"Package Manager","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP provides a powerful package manager for protobuf dependencies that simplifies dependency management through a decentralized, Git-based approach. Unlike centralized solutions, EasyP works directly with Git repositor","content":"EasyP provides a powerful package manager for protobuf dependencies that simplifies dependency management through a decentralized, Git-based approach. Unlike centralized solutions, EasyP works directly with Git repositories, giving you complete control over your dependencies."},{"id":"cli/package-manager/package-manager::overview::1","title":"Package Manager","section":"Overview","path":"/docs/guide/cli/package-manager/package-manager#overview","headings":["Overview"],"excerpt":"Overview The EasyP package manager follows the **Go modules philosophy** - any Git repository can serve as a package source. This approach provides several key advantages:","content":"Overview The EasyP package manager follows the **Go modules philosophy** - any Git repository can serve as a package source. This approach provides several key advantages:"},{"id":"cli/package-manager/package-manager::overview::2","title":"Package Manager","section":"Overview","path":"/docs/guide/cli/package-manager/package-manager#overview","headings":["Overview"],"excerpt":"Overview **Decentralized**: No single point of failure or control **Security**: Direct access to source repositories **Flexibility**: Support for public, private, and enterprise repositories **Reproducibility**: Lock fil","content":"Overview **Decentralized**: No single point of failure or control **Security**: Direct access to source repositories **Flexibility**: Support for public, private, and enterprise repositories **Reproducibility**: Lock files ensure consistent builds across environments **Performance**: Local caching minimizes network requests"},{"id":"cli/package-manager/package-manager::key-features::3","title":"Package Manager","section":"Key Features","path":"/docs/guide/cli/package-manager/package-manager#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- **Git-Native** Works with any Git repository - no special server required **Multiple Version Formats** Tags, commits, pseudo-versions, latest **Lock Files** Reprod","content":"Key Features Feature Description --------- ------------- **Git-Native** Works with any Git repository - no special server required **Multiple Version Formats** Tags, commits, pseudo-versions, latest **Lock Files** Reproducible builds with easyp.lock **Local Caching** Go modules-style cache architecture **Vendoring Support** Copy dependencies locally for offline builds **YAML Configuration** Simple, readable dependency declarations"},{"id":"cli/package-manager/package-manager::architecture::4","title":"Package Manager","section":"Architecture","path":"/docs/guide/cli/package-manager/package-manager#architecture","headings":["Architecture"],"excerpt":"Architecture EasyP uses a two-tier caching system inspired by Go modules:","content":"Architecture EasyP uses a two-tier caching system inspired by Go modules:"},{"id":"cli/package-manager/package-manager::cache-location::5","title":"Package Manager","section":"Cache Location","path":"/docs/guide/cli/package-manager/package-manager#cache-location","headings":["Cache Location"],"excerpt":"Cache Location Environment Location How to Set ------------- ---------- ------------ **Default** $HOME/.easyp Automatic **Custom** Any directory Set EASYPPATH environment variable **CI/CD** Project-relative export EASYPP","content":"Cache Location Environment Location How to Set ------------- ---------- ------------ **Default** $HOME/.easyp Automatic **Custom** Any directory Set EASYPPATH environment variable **CI/CD** Project-relative export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::basic-configuration::6","title":"Package Manager","section":"Basic Configuration","path":"/docs/guide/cli/package-manager/package-manager#basic-configuration","headings":["Basic Configuration"],"excerpt":"Basic Configuration Configure dependencies in your easyp.yaml file:","content":"Basic Configuration Configure dependencies in your easyp.yaml file:"},{"id":"cli/package-manager/package-manager::advanced-configuration-examples::7","title":"Package Manager","section":"Advanced Configuration Examples","path":"/docs/guide/cli/package-manager/package-manager#advanced-configuration-examples","headings":["Advanced Configuration Examples"],"excerpt":"Advanced Configuration Examples","content":"Advanced Configuration Examples"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Package Manager","section":"Multi-Environment Setup","path":"/docs/guide/cli/package-manager/package-manager#multi-environment-setup","headings":["Multi-Environment Setup"],"excerpt":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Latest for development - github.com/mycompany/internal-protos # Latest internal changes - github.com/bufbuild/protoc-gen-v","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Latest for development - github.com/mycompany/internal-protos # Latest internal changes - github.com/bufbuild/protoc-gen-validate # Latest features"},{"id":"cli/package-manager/package-manager::multi-environment-setup::9","title":"Package Manager","section":"Multi-Environment Setup","path":"/docs/guide/cli/package-manager/package-manager#multi-environment-setup","headings":["Multi-Environment Setup"],"excerpt":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Pinned - github.com/mycompany/internal-protos@v2.1.0 # Stable release - github.com/bufbuild/protoc-gen-validate","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Pinned - github.com/mycompany/internal-protos@v2.1.0 # Stable release - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Tested version ```"},{"id":"cli/package-manager/package-manager::private-repository-setup::10","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup ```yaml deps: # Public dependencies - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Private Repository Setup ```yaml deps: # Public dependencies - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::private-repository-setup::11","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup Private company repositories - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Private Repository Setup Private company repositories - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::private-repository-setup::12","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup Internal GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Private Repository Setup Internal GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::versioning-strategies::13","title":"Package Manager","section":"Versioning Strategies","path":"/docs/guide/cli/package-manager/package-manager#versioning-strategies","headings":["Versioning Strategies"],"excerpt":"Versioning Strategies EasyP supports multiple versioning approaches to fit different development workflows:","content":"Versioning Strategies EasyP supports multiple versioning approaches to fit different development workflows:"},{"id":"cli/package-manager/package-manager::1-semantic-version-tags-recommended-for-production::14","title":"Package Manager","section":"1. Semantic Version Tags (Recommended for Production)","path":"/docs/guide/cli/package-manager/package-manager#1-semantic-version-tags-recommended-for-production","headings":["1. Semantic Version Tags (Recommended for Production)"],"excerpt":"Semantic Version Tags (Recommended for Production)","content":"Semantic Version Tags (Recommended for Production)"},{"id":"cli/package-manager/package-manager::1-semantic-version-tags-recommended-for-production::15","title":"Package Manager","section":"1. Semantic Version Tags (Recommended for Production)","path":"/docs/guide/cli/package-manager/package-manager#1-semantic-version-tags-recommended-for-production","headings":["1. Semantic Version Tags (Recommended for Production)"],"excerpt":"Semantic Version Tags (Recommended for Production) **Use when:** Production deployments Stable API consumption Reproducible builds required","content":"Semantic Version Tags (Recommended for Production) **Use when:** Production deployments Stable API consumption Reproducible builds required"},{"id":"cli/package-manager/package-manager::2-latest-tag-development::16","title":"Package Manager","section":"2. Latest Tag (Development)","path":"/docs/guide/cli/package-manager/package-manager#2-latest-tag-development","headings":["2. Latest Tag (Development)"],"excerpt":"Latest Tag (Development) **Use when:** Active development Want latest features Compatibility testing","content":"Latest Tag (Development) **Use when:** Active development Want latest features Compatibility testing"},{"id":"cli/package-manager/package-manager::3-commit-hashes-bleeding-edge::17","title":"Package Manager","section":"3. Commit Hashes (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-commit-hashes-bleeding-edge","headings":["3. Commit Hashes (Bleeding Edge)"],"excerpt":"Commit Hashes (Bleeding Edge) **Use when:** Need unreleased features Testing specific fixes Contributing to upstream","content":"Commit Hashes (Bleeding Edge) **Use when:** Need unreleased features Testing specific fixes Contributing to upstream"},{"id":"cli/package-manager/package-manager::4-pseudo-versions-automatic::18","title":"Package Manager","section":"4. Pseudo-Versions (Automatic)","path":"/docs/guide/cli/package-manager/package-manager#4-pseudo-versions-automatic","headings":["4. Pseudo-Versions (Automatic)"],"excerpt":"Pseudo-Versions (Automatic) When EasyP can't find a suitable tag, it generates pseudo-versions automatically:","content":"Pseudo-Versions (Automatic) When EasyP can't find a suitable tag, it generates pseudo-versions automatically:"},{"id":"cli/package-manager/package-manager::4-pseudo-versions-automatic::19","title":"Package Manager","section":"4. Pseudo-Versions (Automatic)","path":"/docs/guide/cli/package-manager/package-manager#4-pseudo-versions-automatic","headings":["4. Pseudo-Versions (Automatic)"],"excerpt":"Pseudo-Versions (Automatic) This ensures every commit can be referenced with a version-like identifier.","content":"Pseudo-Versions (Automatic) This ensures every commit can be referenced with a version-like identifier."},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Downloads and installs all dependencies declared in your configuration.","content":"easyp mod download Downloads and installs all dependencies declared in your configuration."},{"id":"cli/package-manager/package-manager::easyp-mod-download::21","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **What happens:** **Resolves versions**: Converts tags/latest to specific commits **Downloads archives**: Stores .zip files in cache/download **Verifies checksums**: Ensures archive integrity **Extract","content":"easyp mod download **What happens:** **Resolves versions**: Converts tags/latest to specific commits **Downloads archives**: Stores .zip files in cache/download **Verifies checksums**: Ensures archive integrity **Extracts modules**: Unpacks to cache/mod with proper structure **Updates lock file**: Records exact versions and content hashes"},{"id":"cli/package-manager/package-manager::easyp-mod-download::22","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Usage:** ```bash Use default easyp.yaml easyp mod download","content":"easyp mod download **Usage:** ```bash Use default easyp.yaml easyp mod download"},{"id":"cli/package-manager/package-manager::easyp-mod-download::23","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Use custom config file easyp --cfg production.easyp.yaml mod download","content":"easyp mod download Use custom config file easyp --cfg production.easyp.yaml mod download"},{"id":"cli/package-manager/package-manager::easyp-mod-download::24","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download With custom cache location EASYPPATH=/tmp/easyp-cache easyp mod download ```","content":"easyp mod download With custom cache location EASYPPATH=/tmp/easyp-cache easyp mod download ```"},{"id":"cli/package-manager/package-manager::easyp-mod-download::25","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Example output:**","content":"easyp mod download **Example output:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::26","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Copies all installed proto files to a local easyp_vendor/ directory for offline usage.","content":"easyp mod vendor Copies all installed proto files to a local easyp_vendor/ directory for offline usage."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::27","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Use cases:** **Docker builds**: Avoid network dependencies in containers **Air-gapped environments**: No internet access during builds **Reproducible builds**: Bundle exact dependency versions **Perfor","content":"easyp mod vendor **Use cases:** **Docker builds**: Avoid network dependencies in containers **Air-gapped environments**: No internet access during builds **Reproducible builds**: Bundle exact dependency versions **Performance**: Eliminate network latency in repeated builds"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::28","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Result structure:**","content":"easyp mod vendor **Result structure:**"},{"id":"cli/package-manager/package-manager::easyp-mod-update::29","title":"Package Manager","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Updates module versions based on current configuration and writes resolved versions to the lock file.","content":"easyp mod update Updates module versions based on current configuration and writes resolved versions to the lock file."},{"id":"cli/package-manager/package-manager::easyp-mod-update::30","title":"Package Manager","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update **Behavior:** Respects version constraints in easyp.yaml Updates to latest compatible versions Regenerates easyp.lock with new versions and hashes","content":"easyp mod update **Behavior:** Respects version constraints in easyp.yaml Updates to latest compatible versions Regenerates easyp.lock with new versions and hashes"},{"id":"cli/package-manager/package-manager::lock-files::31","title":"Package Manager","section":"Lock Files","path":"/docs/guide/cli/package-manager/package-manager#lock-files","headings":["Lock Files"],"excerpt":"Lock Files The easyp.lock file ensures reproducible builds by recording exact versions and content hashes:","content":"Lock Files The easyp.lock file ensures reproducible builds by recording exact versions and content hashes:"},{"id":"cli/package-manager/package-manager::lock-file-format::32","title":"Package Manager","section":"Lock File Format","path":"/docs/guide/cli/package-manager/package-manager#lock-file-format","headings":["Lock File Format"],"excerpt":"Lock File Format Each line contains three components: **Module path**: Full repository path **Exact version**: Resolved version (tag or pseudo-version) **Content hash**: SHA256 of extracted content (h1: prefix)","content":"Lock File Format Each line contains three components: **Module path**: Full repository path **Exact version**: Resolved version (tag or pseudo-version) **Content hash**: SHA256 of extracted content (h1: prefix)"},{"id":"cli/package-manager/package-manager::best-practices::33","title":"Package Manager","section":"Best Practices","path":"/docs/guide/cli/package-manager/package-manager#best-practices","headings":["Best Practices"],"excerpt":"Best Practices ✅ **Always commit easyp.lock** - Ensures team consistency ✅ **Run mod update deliberately** - Don't auto-update in CI ✅ **Review lock changes** - Understand what's being updated ❌ **Don't edit manually** -","content":"Best Practices ✅ **Always commit easyp.lock** - Ensures team consistency ✅ **Run mod update deliberately** - Don't auto-update in CI ✅ **Review lock changes** - Understand what's being updated ❌ **Don't edit manually** - Let EasyP manage the format"},{"id":"cli/package-manager/package-manager::public-repositories::34","title":"Package Manager","section":"Public Repositories","path":"/docs/guide/cli/package-manager/package-manager#public-repositories","headings":["Public Repositories"],"excerpt":"Public Repositories No setup required - works out of the box:","content":"Public Repositories No setup required - works out of the box:"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::35","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) Configure Git to use SSH for GitHub/GitLab:","content":"SSH Keys (Recommended) Configure Git to use SSH for GitHub/GitLab:"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::36","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) ```bash For GitHub git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\"","content":"SSH Keys (Recommended) ```bash For GitHub git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\""},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::37","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) For GitLab git config --global url.\"git@gitlab.com:\".insteadOf \"https://gitlab.com/\"","content":"SSH Keys (Recommended) For GitLab git config --global url.\"git@gitlab.com:\".insteadOf \"https://gitlab.com/\""},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::38","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) For custom domains git config --global url.\"git@gitlab.company.com:\".insteadOf \"https://gitlab.company.com/\" ```","content":"SSH Keys (Recommended) For custom domains git config --global url.\"git@gitlab.company.com:\".insteadOf \"https://gitlab.company.com/\" ```"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::39","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) Then use normal HTTPS URLs in your config:","content":"SSH Keys (Recommended) Then use normal HTTPS URLs in your config:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::40","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens For HTTPS authentication:","content":"Personal Access Tokens For HTTPS authentication:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::41","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash Method 1: Credential helper git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash Method 1: Credential helper git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::42","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens Method 2: URL rewriting git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens Method 2: URL rewriting git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::corporate-environments::43","title":"Package Manager","section":"Corporate Environments","path":"/docs/guide/cli/package-manager/package-manager#corporate-environments","headings":["Corporate Environments"],"excerpt":"Corporate Environments ```bash Configure proxy git config --global http.proxy http://proxy.company.com:8080 git config --global https.proxy https://proxy.company.com:8080","content":"Corporate Environments ```bash Configure proxy git config --global http.proxy http://proxy.company.com:8080 git config --global https.proxy https://proxy.company.com:8080"},{"id":"cli/package-manager/package-manager::corporate-environments::44","title":"Package Manager","section":"Corporate Environments","path":"/docs/guide/cli/package-manager/package-manager#corporate-environments","headings":["Corporate Environments"],"excerpt":"Corporate Environments Configure certificates for internal Git servers git config --global http.sslCAInfo /path/to/certificate.pem ```","content":"Corporate Environments Configure certificates for internal Git servers git config --global http.sslCAInfo /path/to/certificate.pem ```"},{"id":"cli/package-manager/package-manager::initial-project-setup::45","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup ```bash Create configuration cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Initial Project Setup ```bash Create configuration cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF"},{"id":"cli/package-manager/package-manager::initial-project-setup::46","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup Download dependencies easyp mod download","content":"Initial Project Setup Download dependencies easyp mod download"},{"id":"cli/package-manager/package-manager::initial-project-setup::47","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup Verify installation ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Initial Project Setup Verify installation ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::48","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies ```bash Edit easyp.yaml echo \" - github.com/bufbuild/protoc-gen-validate@v0.10.1\" >> easyp.yaml","content":"Adding New Dependencies ```bash Edit easyp.yaml echo \" - github.com/bufbuild/protoc-gen-validate@v0.10.1\" >> easyp.yaml"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::49","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies Download new dependency easyp mod download","content":"Adding New Dependencies Download new dependency easyp mod download"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::50","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies Commit lock file changes git add easyp.lock git commit -m \"Add protoc-gen-validate dependency\" ```","content":"Adding New Dependencies Commit lock file changes git add easyp.lock git commit -m \"Add protoc-gen-validate dependency\" ```"},{"id":"cli/package-manager/package-manager::updating-dependencies::51","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies ```bash Update to latest compatible versions easyp mod update","content":"Updating Dependencies ```bash Update to latest compatible versions easyp mod update"},{"id":"cli/package-manager/package-manager::updating-dependencies::52","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Review changes git diff easyp.lock","content":"Updating Dependencies Review changes git diff easyp.lock"},{"id":"cli/package-manager/package-manager::updating-dependencies::53","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Test with new versions easyp generate easyp lint","content":"Updating Dependencies Test with new versions easyp generate easyp lint"},{"id":"cli/package-manager/package-manager::updating-dependencies::54","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Commit if everything works git add easyp.lock git commit -m \"Update dependencies\" ```","content":"Updating Dependencies Commit if everything works git add easyp.lock git commit -m \"Update dependencies\" ```"},{"id":"cli/package-manager/package-manager::offline-development::55","title":"Package Manager","section":"Offline Development","path":"/docs/guide/cli/package-manager/package-manager#offline-development","headings":["Offline Development"],"excerpt":"Offline Development ```bash Vendor all dependencies easyp mod vendor","content":"Offline Development ```bash Vendor all dependencies easyp mod vendor"},{"id":"cli/package-manager/package-manager::offline-development::56","title":"Package Manager","section":"Offline Development","path":"/docs/guide/cli/package-manager/package-manager#offline-development","headings":["Offline Development"],"excerpt":"Offline Development Now your project works offline easyp generate ```","content":"Offline Development Now your project works offline easyp generate ```"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::57","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" **Problem**: Can't access private repository **Solution**: Check authentication setup","content":"\"Repository not found\" or \"Authentication failed\" **Problem**: Can't access private repository **Solution**: Check authentication setup"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::58","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" ```bash Test Git access git ls-remote https://github.com/mycompany/private-repo","content":"\"Repository not found\" or \"Authentication failed\" ```bash Test Git access git ls-remote https://github.com/mycompany/private-repo"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::59","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" Check Git configuration git config --list grep url ```","content":"\"Repository not found\" or \"Authentication failed\" Check Git configuration git config --list grep url ```"},{"id":"cli/package-manager/package-manager::version-not-found::60","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" **Problem**: Specified tag/version doesn't exist **Solution**: Check available tags","content":"\"Version not found\" **Problem**: Specified tag/version doesn't exist **Solution**: Check available tags"},{"id":"cli/package-manager/package-manager::version-not-found::61","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" ```bash List available tags git ls-remote --tags https://github.com/googleapis/googleapis","content":"\"Version not found\" ```bash List available tags git ls-remote --tags https://github.com/googleapis/googleapis"},{"id":"cli/package-manager/package-manager::version-not-found::62","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" Use existing tag or commit hash deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Valid tag ```","content":"\"Version not found\" Use existing tag or commit hash deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Valid tag ```"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::63","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" **Problem**: Corrupted cache files **Solution**: Clear cache and re-download","content":"\"Cache corruption\" or \"Checksum mismatch\" **Problem**: Corrupted cache files **Solution**: Clear cache and re-download"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::64","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" ```bash Clear everything rm -rf ~/.easyp","content":"\"Cache corruption\" or \"Checksum mismatch\" ```bash Clear everything rm -rf ~/.easyp"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::65","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" Or clear just downloads rm -rf ~/.easyp/cache/download","content":"\"Cache corruption\" or \"Checksum mismatch\" Or clear just downloads rm -rf ~/.easyp/cache/download"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::66","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" Re-download easyp mod download ```","content":"\"Cache corruption\" or \"Checksum mismatch\" Re-download easyp mod download ```"},{"id":"cli/package-manager/package-manager::network-timeouts::67","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts **Problem**: Slow or unreliable network **Solution**: Configure Git timeouts","content":"Network timeouts **Problem**: Slow or unreliable network **Solution**: Configure Git timeouts"},{"id":"cli/package-manager/package-manager::network-timeouts::68","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts ```bash Increase timeout git config --global http.lowSpeedLimit 1000 git config --global http.lowSpeedTime 300","content":"Network timeouts ```bash Increase timeout git config --global http.lowSpeedLimit 1000 git config --global http.lowSpeedTime 300"},{"id":"cli/package-manager/package-manager::network-timeouts::69","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts Use proxy if available git config --global http.proxy http://proxy.company.com:8080 ```","content":"Network timeouts Use proxy if available git config --global http.proxy http://proxy.company.com:8080 ```"},{"id":"cli/package-manager/package-manager::for-large-teams::70","title":"Package Manager","section":"For Large Teams","path":"/docs/guide/cli/package-manager/package-manager#for-large-teams","headings":["For Large Teams"],"excerpt":"For Large Teams ```bash Use shared cache server (if available) export EASYPPATH=/shared/easyp-cache","content":"For Large Teams ```bash Use shared cache server (if available) export EASYPPATH=/shared/easyp-cache"},{"id":"cli/package-manager/package-manager::for-large-teams::71","title":"Package Manager","section":"For Large Teams","path":"/docs/guide/cli/package-manager/package-manager#for-large-teams","headings":["For Large Teams"],"excerpt":"For Large Teams Or use team-specific cache export EASYPPATH=/team-cache/easyp ```","content":"For Large Teams Or use team-specific cache export EASYPPATH=/team-cache/easyp ```"},{"id":"cli/package-manager/package-manager::for-cicd-systems::72","title":"Package Manager","section":"For CI/CD Systems","path":"/docs/guide/cli/package-manager/package-manager#for-cicd-systems","headings":["For CI/CD Systems"],"excerpt":"For CI/CD Systems ```bash Use project-relative cache export EASYPPATH=$CI_PROJECT_DIR/.easyp","content":"For CI/CD Systems ```bash Use project-relative cache export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::for-cicd-systems::73","title":"Package Manager","section":"For CI/CD Systems","path":"/docs/guide/cli/package-manager/package-manager#for-cicd-systems","headings":["For CI/CD Systems"],"excerpt":"For CI/CD Systems Cache between builds (GitLab CI example) cache: key: easyp-$CI_COMMIT_REF_SLUG paths: - .easyp/ ```","content":"For CI/CD Systems Cache between builds (GitLab CI example) cache: key: easyp-$CI_COMMIT_REF_SLUG paths: - .easyp/ ```"},{"id":"cli/package-manager/package-manager::cache-size-management::74","title":"Package Manager","section":"Cache Size Management","path":"/docs/guide/cli/package-manager/package-manager#cache-size-management","headings":["Cache Size Management"],"excerpt":"Cache Size Management ```bash Check cache usage du -sh ~/.easyp du -sh ~/.easyp/cache/download # Archives only du -sh ~/.easyp/mod # Extracted modules","content":"Cache Size Management ```bash Check cache usage du -sh ~/.easyp du -sh ~/.easyp/cache/download # Archives only du -sh ~/.easyp/mod # Extracted modules"},{"id":"cli/package-manager/package-manager::cache-size-management::75","title":"Package Manager","section":"Cache Size Management","path":"/docs/guide/cli/package-manager/package-manager#cache-size-management","headings":["Cache Size Management"],"excerpt":"Cache Size Management Clean old versions (manual) find ~/.easyp/mod -type d -name \"v0.0.0-*\" -mtime +30 -exec rm -rf {} \\; ```","content":"Cache Size Management Clean old versions (manual) find ~/.easyp/mod -type d -name \"v0.0.0-*\" -mtime +30 -exec rm -rf {} \\; ```"},{"id":"cli/package-manager/package-manager::docker-multi-stage-build::76","title":"Package Manager","section":"Docker Multi-stage Build","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage-build","headings":["Docker Multi-stage Build"],"excerpt":"Docker Multi-stage Build ```dockerfile Stage 1: Download dependencies FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker Multi-stage Build ```dockerfile Stage 1: Download dependencies FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor"},{"id":"cli/package-manager/package-manager::docker-multi-stage-build::77","title":"Package Manager","section":"Docker Multi-stage Build","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage-build","headings":["Docker Multi-stage Build"],"excerpt":"Docker Multi-stage Build Stage 2: Build application FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . Use vendored dependencies for generation RUN easyp generate ``","content":"Docker Multi-stage Build Stage 2: Build application FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . Use vendored dependencies for generation RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo-structure::78","title":"Package Manager","section":"Monorepo Structure","path":"/docs/guide/cli/package-manager/package-manager#monorepo-structure","headings":["Monorepo Structure"],"excerpt":"Monorepo Structure Each easyp.yaml can have different dependencies based on service needs.","content":"Monorepo Structure Each easyp.yaml can have different dependencies based on service needs."},{"id":"cli/package-manager/package-manager::development-workflow::79","title":"Package Manager","section":"Development Workflow","path":"/docs/guide/cli/package-manager/package-manager#development-workflow","headings":["Development Workflow"],"excerpt":"Development Workflow ✅ Use **latest tags** during active development ✅ **Pin versions** for production deployments ✅ **Commit lock files** to ensure reproducibility ✅ **Review dependency updates** before merging ✅ **Test","content":"Development Workflow ✅ Use **latest tags** during active development ✅ **Pin versions** for production deployments ✅ **Commit lock files** to ensure reproducibility ✅ **Review dependency updates** before merging ✅ **Test after updates** to catch compatibility issues"},{"id":"cli/package-manager/package-manager::security::80","title":"Package Manager","section":"Security","path":"/docs/guide/cli/package-manager/package-manager#security","headings":["Security"],"excerpt":"Security ✅ **Pin to specific versions** in production ✅ **Use SSH keys** for private repositories ✅ **Review new dependencies** for security implications ✅ **Monitor for vulnerabilities** in dependencies ❌ **Don't embed ","content":"Security ✅ **Pin to specific versions** in production ✅ **Use SSH keys** for private repositories ✅ **Review new dependencies** for security implications ✅ **Monitor for vulnerabilities** in dependencies ❌ **Don't embed credentials** in configuration files"},{"id":"cli/package-manager/package-manager::performance::81","title":"Package Manager","section":"Performance","path":"/docs/guide/cli/package-manager/package-manager#performance","headings":["Performance"],"excerpt":"Performance ✅ **Cache aggressively** in CI/CD systems ✅ **Use vendoring** for frequently rebuilt projects ✅ **Clean old cache** periodically to save space ✅ **Use shared cache** for team environments","content":"Performance ✅ **Cache aggressively** in CI/CD systems ✅ **Use vendoring** for frequently rebuilt projects ✅ **Clean old cache** periodically to save space ✅ **Use shared cache** for team environments"},{"id":"cli/package-manager/package-manager::team-collaboration::82","title":"Package Manager","section":"Team Collaboration","path":"/docs/guide/cli/package-manager/package-manager#team-collaboration","headings":["Team Collaboration"],"excerpt":"Team Collaboration ✅ **Document authentication setup** for new team members ✅ **Use consistent tooling** across environments ✅ **Automate dependency updates** with proper testing ✅ **Share cache locations** when possible","content":"Team Collaboration ✅ **Document authentication setup** for new team members ✅ **Use consistent tooling** across environments ✅ **Automate dependency updates** with proper testing ✅ **Share cache locations** when possible"},{"id":"cli/package-manager/package-manager::team-collaboration::83","title":"Package Manager","section":"Team Collaboration","path":"/docs/guide/cli/package-manager/package-manager#team-collaboration","headings":["Team Collaboration"],"excerpt":"Team Collaboration The EasyP package manager provides a robust, decentralized solution for protobuf dependency management that scales from individual projects to enterprise environments while maintaining the simplicity a","content":"Team Collaboration The EasyP package manager provides a robust, decentralized solution for protobuf dependency management that scales from individual projects to enterprise environments while maintaining the simplicity and reliability developers expect."},{"id":"introduction/install::install-from-systems-package-manager::0","title":"Install the EasyP cli","section":"Install from system's package manager","path":"/docs/guide/introduction/install#install-from-systems-package-manager","headings":["Install from system's package manager"],"excerpt":"Install from system's package manager","content":"Install from system's package manager"},{"id":"introduction/install::recommended-installation-method::1","title":"Install the EasyP cli","section":"Recommended installation method","path":"/docs/guide/introduction/install#recommended-installation-method","headings":["Recommended installation method"],"excerpt":"Recommended installation method","content":"Recommended installation method"},{"id":"introduction/install::homebrew::2","title":"Install the EasyP cli","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew You can install a binary release on macOS using brew:","content":"Homebrew You can install a binary release on macOS using brew:"},{"id":"introduction/install::homebrew::3","title":"Install the EasyP cli","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress apt, yum, pacman, etc.","content":"Homebrew Work in progress apt, yum, pacman, etc."},{"id":"introduction/install::_not-recommended_::4","title":"Install the EasyP cli","section":"_Not recommended_","path":"/docs/guide/introduction/install#_not-recommended_","headings":["_Not recommended_"],"excerpt":"_Not recommended_ Local installation is not recommended because package managers provide: Automatic updates and security patches Better integration with system package management Easier installation and removal process V","content":"_Not recommended_ Local installation is not recommended because package managers provide: Automatic updates and security patches Better integration with system package management Easier installation and removal process Verified and signed binaries"},{"id":"introduction/install::go-install::5","title":"Install the EasyP cli","section":"Go install","path":"/docs/guide/introduction/install#go-install","headings":["Go install"],"excerpt":"Go install It will install the latest stable version of easyp.","content":"Go install It will install the latest stable version of easyp."},{"id":"introduction/install::build-from-source::6","title":"Install the EasyP cli","section":"Build from source","path":"/docs/guide/introduction/install#build-from-source","headings":["Build from source"],"excerpt":"Build from source Clone repository","content":"Build from source Clone repository"},{"id":"introduction/install::build-from-source::7","title":"Install the EasyP cli","section":"Build from source","path":"/docs/guide/introduction/install#build-from-source","headings":["Build from source"],"excerpt":"Build from source Build by golang","content":"Build from source Build by golang"},{"id":"introduction/quickstart::top::0","title":"Quickstart","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP is a modern toolkit for working with Protobuf files. In this quickstart, you'll learn to:","content":"EasyP is a modern toolkit for working with Protobuf files. In this quickstart, you'll learn to:"},{"id":"introduction/quickstart::top::1","title":"Quickstart","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Initialize** your project with EasyP configuration **Set up linting** to catch errors and ensure best practices **Manage dependencies** from Git repositories **Generate code** from your Protobuf files","content":"**Initialize** your project with EasyP configuration **Set up linting** to catch errors and ensure best practices **Manage dependencies** from Git repositories **Generate code** from your Protobuf files"},{"id":"introduction/quickstart::prerequisites::2","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites Before you begin, make sure you have:","content":"Prerequisites Before you begin, make sure you have:"},{"id":"introduction/quickstart::prerequisites::3","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites **EasyP CLI installed** - See Installation guide if you haven't already **Git** installed and in your $PATH **Protobuf files** ready to work with (or create some as you go)","content":"Prerequisites **EasyP CLI installed** - See Installation guide if you haven't already **Git** installed and in your $PATH **Protobuf files** ready to work with (or create some as you go)"},{"id":"introduction/quickstart::prerequisites::4","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites You can verify your installation:","content":"Prerequisites You can verify your installation:"},{"id":"introduction/quickstart::initialize-your-project::5","title":"Quickstart","section":"Initialize your project","path":"/docs/guide/introduction/quickstart#initialize-your-project","headings":["Initialize your project"],"excerpt":"Initialize your project Start by creating an easyp.yaml configuration file in your project root:","content":"Initialize your project Start by creating an easyp.yaml configuration file in your project root:"},{"id":"introduction/quickstart::initialize-your-project::6","title":"Quickstart","section":"Initialize your project","path":"/docs/guide/introduction/quickstart#initialize-your-project","headings":["Initialize your project"],"excerpt":"Initialize your project This command generates a commented template with default lint and breaking settings. easyp init is interactive: if buf.yml/buf.yaml exists in the target root, EasyP asks whether to migrate it; if ","content":"Initialize your project This command generates a commented template with default lint and breaking settings. easyp init is interactive: if buf.yml/buf.yaml exists in the target root, EasyP asks whether to migrate it; if easyp.yaml already exists, it asks before overwriting."},{"id":"introduction/quickstart::configure-linting::7","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting Linting helps catch errors and ensures your Protobuf files follow best practices. EasyP provides default rules compatible with Buf standards.","content":"Configure linting Linting helps catch errors and ensures your Protobuf files follow best practices. EasyP provides default rules compatible with Buf standards."},{"id":"introduction/quickstart::configure-linting::8","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting easyp init already generates a lint section. Adjust it if needed, for example:","content":"Configure linting easyp init already generates a lint section. Adjust it if needed, for example:"},{"id":"introduction/quickstart::configure-linting::9","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting Now you can run the linter:","content":"Configure linting Now you can run the linter:"},{"id":"introduction/quickstart::configure-linting::10","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting The linter will check all your .proto files and report any issues found.","content":"Configure linting The linter will check all your .proto files and report any issues found."},{"id":"introduction/quickstart::configure-linting::11","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting ::: tip EasyP's linting rules are 100% compatible with Buf, making migration easy if you're switching tools. :::","content":"Configure linting ::: tip EasyP's linting rules are 100% compatible with Buf, making migration easy if you're switching tools. :::"},{"id":"introduction/quickstart::manage-dependencies::12","title":"Quickstart","section":"Manage dependencies","path":"/docs/guide/introduction/quickstart#manage-dependencies","headings":["Manage dependencies"],"excerpt":"Manage dependencies If your project uses third-party Protobuf packages (like Google APIs or gRPC Gateway), EasyP makes it easy to manage them.","content":"Manage dependencies If your project uses third-party Protobuf packages (like Google APIs or gRPC Gateway), EasyP makes it easy to manage them."},{"id":"introduction/quickstart::dependency-format::13","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format Dependencies use a simple format: $GIT_LINK@$VERSION","content":"Dependency format Dependencies use a simple format: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::dependency-format::14","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format **$GIT_LINK** - URL to any Git repository (GitHub, GitLab, etc.) **$VERSION** - Git tag or commit hash (optional)","content":"Dependency format **$GIT_LINK** - URL to any Git repository (GitHub, GitLab, etc.) **$VERSION** - Git tag or commit hash (optional)"},{"id":"introduction/quickstart::dependency-format::15","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format If you omit the version, EasyP downloads the latest commit from the default branch.","content":"Dependency format If you omit the version, EasyP downloads the latest commit from the default branch."},{"id":"introduction/quickstart::add-dependencies::16","title":"Quickstart","section":"Add dependencies","path":"/docs/guide/introduction/quickstart#add-dependencies","headings":["Add dependencies"],"excerpt":"Add dependencies Update your easyp.yaml to include dependencies:","content":"Add dependencies Update your easyp.yaml to include dependencies:"},{"id":"introduction/quickstart::download-dependencies::17","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies Download the packages you specified:","content":"Download dependencies Download the packages you specified:"},{"id":"introduction/quickstart::download-dependencies::18","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies This command: Downloads dependencies from easyp.lock if it exists Otherwise, downloads from easyp.yaml and creates easyp.lock","content":"Download dependencies This command: Downloads dependencies from easyp.lock if it exists Otherwise, downloads from easyp.yaml and creates easyp.lock"},{"id":"introduction/quickstart::download-dependencies::19","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies ::: info **Tip:** Use easyp mod update to ignore the lock file and fetch the latest versions from easyp.yaml. :::","content":"Download dependencies ::: info **Tip:** Use easyp mod update to ignore the lock file and fetch the latest versions from easyp.yaml. :::"},{"id":"introduction/quickstart::generate-code::20","title":"Quickstart","section":"Generate code","path":"/docs/guide/introduction/quickstart#generate-code","headings":["Generate code"],"excerpt":"Generate code Now let's configure code generation. EasyP supports all standard Protobuf plugins.","content":"Generate code Now let's configure code generation. EasyP supports all standard Protobuf plugins."},{"id":"introduction/quickstart::configure-generation::21","title":"Quickstart","section":"Configure generation","path":"/docs/guide/introduction/quickstart#configure-generation","headings":["Configure generation"],"excerpt":"Configure generation Add plugin configuration to your easyp.yaml:","content":"Configure generation Add plugin configuration to your easyp.yaml:"},{"id":"introduction/quickstart::run-code-generation::22","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation Generate your code stubs:","content":"Run code generation Generate your code stubs:"},{"id":"introduction/quickstart::run-code-generation::23","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation EasyP will: Resolve all dependencies Connect to the EasyP service (or run locally) Execute the configured plugins Output generated code to the specified directories","content":"Run code generation EasyP will: Resolve all dependencies Connect to the EasyP service (or run locally) Execute the configured plugins Output generated code to the specified directories"},{"id":"introduction/quickstart::run-code-generation::24","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation ::: tip EasyP uses a hybrid runtime with WASM for speed and Docker for heavy plugins, giving you the best of both worlds. :::","content":"Run code generation ::: tip EasyP uses a hybrid runtime with WASM for speed and Docker for heavy plugins, giving you the best of both worlds. :::"},{"id":"introduction/quickstart::next-steps::25","title":"Quickstart","section":"Next steps","path":"/docs/guide/introduction/quickstart#next-steps","headings":["Next steps"],"excerpt":"Next steps Congratulations! 🎉 You've successfully: ✅ Initialized an EasyP project ✅ Configured linting rules ✅ Managed third-party dependencies ✅ Generated code from your Protobuf files","content":"Next steps Congratulations! 🎉 You've successfully: ✅ Initialized an EasyP project ✅ Configured linting rules ✅ Managed third-party dependencies ✅ Generated code from your Protobuf files"},{"id":"introduction/quickstart::learn-more::26","title":"Quickstart","section":"Learn more","path":"/docs/guide/introduction/quickstart#learn-more","headings":["Learn more"],"excerpt":"Learn more **CLI Reference** - Deep dive into all CLI commands **API Service** - Set up remote code generation **Configuration** - Explore all configuration options","content":"Learn more **CLI Reference** - Deep dive into all CLI commands **API Service** - Set up remote code generation **Configuration** - Explore all configuration options"},{"id":"introduction/quickstart::learn-more::27","title":"Quickstart","section":"Learn more","path":"/docs/guide/introduction/quickstart#learn-more","headings":["Learn more"],"excerpt":"Learn more *Enjoy working with Protobuf without any pain! 🚀*","content":"Learn more *Enjoy working with Protobuf without any pain! 🚀*"},{"id":"introduction/what-is::top::0","title":"What is EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP is a modern Protocol Buffers toolkit that consolidates your entire protobuf workflow into a single, powerful CLI tool. It combines linting, package management, code generation, and compatibility checking in a unifi","content":"EasyP is a modern Protocol Buffers toolkit that consolidates your entire protobuf workflow into a single, powerful CLI tool. It combines linting, package management, code generation, and compatibility checking in a unified interface designed to eliminate the complexity of traditional protobuf development."},{"id":"introduction/what-is::top::1","title":"What is EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Just want to try it out? Skip to the Quickstart.","content":"Just want to try it out? Skip to the Quickstart."},{"id":"introduction/what-is::the-problem-fragmented-proto-workflows::2","title":"What is EasyP?","section":"The Problem: Fragmented Proto Workflows","path":"/docs/guide/introduction/what-is#the-problem-fragmented-proto-workflows","headings":["The Problem: Fragmented Proto Workflows"],"excerpt":"The Problem: Fragmented Proto Workflows Working with Protocol Buffers across projects creates unnecessary complexity and friction:","content":"The Problem: Fragmented Proto Workflows Working with Protocol Buffers across projects creates unnecessary complexity and friction:"},{"id":"introduction/what-is::tool-chaos::3","title":"What is EasyP?","section":"Tool Chaos","path":"/docs/guide/introduction/what-is#tool-chaos","headings":["Tool Chaos"],"excerpt":"Tool Chaos **Multiple tools for different tasks**: Separate tools for linting, generation, and dependency management **Inconsistent configurations**: Different config formats across projects and teams **Complex setup**: ","content":"Tool Chaos **Multiple tools for different tasks**: Separate tools for linting, generation, and dependency management **Inconsistent configurations**: Different config formats across projects and teams **Complex setup**: Time-consuming onboarding for new developers joining projects"},{"id":"introduction/what-is::dependency-management-issues::4","title":"What is EasyP?","section":"Dependency Management Issues","path":"/docs/guide/introduction/what-is#dependency-management-issues","headings":["Dependency Management Issues"],"excerpt":"Dependency Management Issues **No standardized approach**: Each project handles proto dependencies differently **Version conflicts**: Difficult to resolve conflicts between different proto libraries **Build reproducibili","content":"Dependency Management Issues **No standardized approach**: Each project handles proto dependencies differently **Version conflicts**: Difficult to resolve conflicts between different proto libraries **Build reproducibility**: Hard to ensure consistent builds across environments"},{"id":"introduction/what-is::development-friction::5","title":"What is EasyP?","section":"Development Friction","path":"/docs/guide/introduction/what-is#development-friction","headings":["Development Friction"],"excerpt":"Development Friction **Manual processes**: Repetitive workflows for common proto tasks **Configuration sprawl**: Multiple config files with different formats **Time-consuming compatibility checks**: Manual verification o","content":"Development Friction **Manual processes**: Repetitive workflows for common proto tasks **Configuration sprawl**: Multiple config files with different formats **Time-consuming compatibility checks**: Manual verification of API changes"},{"id":"introduction/what-is::the-solution-unified-proto-toolkit::6","title":"What is EasyP?","section":"The Solution: Unified Proto Toolkit","path":"/docs/guide/introduction/what-is#the-solution-unified-proto-toolkit","headings":["The Solution: Unified Proto Toolkit"],"excerpt":"The Solution: Unified Proto Toolkit EasyP addresses these challenges by providing a comprehensive, opinionated toolkit that standardizes protobuf workflows:","content":"The Solution: Unified Proto Toolkit EasyP addresses these challenges by providing a comprehensive, opinionated toolkit that standardizes protobuf workflows:"},{"id":"introduction/what-is::one-tool-all-tasks::7","title":"What is EasyP?","section":"One Tool, All Tasks","path":"/docs/guide/introduction/what-is#one-tool-all-tasks","headings":["One Tool, All Tasks"],"excerpt":"One Tool, All Tasks Instead of juggling multiple tools, EasyP provides everything you need: **Linting** with comprehensive rule sets **Package management** with Git-native dependencies **Code generation** with local and ","content":"One Tool, All Tasks Instead of juggling multiple tools, EasyP provides everything you need: **Linting** with comprehensive rule sets **Package management** with Git-native dependencies **Code generation** with local and remote plugin support **Breaking change detection** for API compatibility"},{"id":"introduction/what-is::standardized-configuration::8","title":"What is EasyP?","section":"Standardized Configuration","path":"/docs/guide/introduction/what-is#standardized-configuration","headings":["Standardized Configuration"],"excerpt":"Standardized Configuration A single easyp.yaml file configures your entire protobuf workflow, eliminating configuration sprawl and ensuring consistency across projects.","content":"Standardized Configuration A single easyp.yaml file configures your entire protobuf workflow, eliminating configuration sprawl and ensuring consistency across projects."},{"id":"introduction/what-is::git-native-dependencies::9","title":"What is EasyP?","section":"Git-Native Dependencies","path":"/docs/guide/introduction/what-is#git-native-dependencies","headings":["Git-Native Dependencies"],"excerpt":"Git-Native Dependencies Direct integration with Git repositories for proto dependencies eliminates the need for centralized registries while providing version control and reproducibility.","content":"Git-Native Dependencies Direct integration with Git repositories for proto dependencies eliminates the need for centralized registries while providing version control and reproducibility."},{"id":"introduction/what-is::key-features::10","title":"What is EasyP?","section":"Key Features","path":"/docs/guide/introduction/what-is#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- 🔍 **Comprehensive Linting** Built-in support for buf's linting rules with customizable configurations to enforce API design best practices. 📦 **Smart Package Man","content":"Key Features Feature Description --------- ------------- 🔍 **Comprehensive Linting** Built-in support for buf's linting rules with customizable configurations to enforce API design best practices. 📦 **Smart Package Manager** Git-based dependency management with lock file support for reproducible builds across environments. ⚡ **Code Generation** Multi-language code generation with support for both local protoc plugins and remote plugin execution. 🔄 **Breaking Change Detection** Automated API compatibility verification against Git branches to prevent accidental breaking changes. 🌐 **Remote Plugin Support** Execute plugins via centralized EasyP API service for consistent, isolated execution without local dependencies. 🎯 **Developer Experience** Auto-completion, intuitive commands, clear error messages, and comprehensive documentation."},{"id":"introduction/what-is::supported-plugin-types::11","title":"What is EasyP?","section":"Supported Plugin Types","path":"/docs/guide/introduction/what-is#supported-plugin-types","headings":["Supported Plugin Types"],"excerpt":"Supported Plugin Types EasyP provides flexibility in how you execute code generation plugins:","content":"Supported Plugin Types EasyP provides flexibility in how you execute code generation plugins:"},{"id":"introduction/what-is::local-plugins::12","title":"What is EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Standard protoc plugins installed on your system:","content":"Local Plugins Standard protoc plugins installed on your system:"},{"id":"introduction/what-is::remote-plugins::13","title":"What is EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Plugins executed via EasyP API service for consistent results:","content":"Remote Plugins Plugins executed via EasyP API service for consistent results:"},{"id":"introduction/what-is::custom-plugins::14","title":"What is EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Support for custom plugin development and distribution through the ecosystem.","content":"Custom Plugins Support for custom plugin development and distribution through the ecosystem."},{"id":"introduction/what-is::decentralized-package-management::15","title":"What is EasyP?","section":"Decentralized Package Management","path":"/docs/guide/introduction/what-is#decentralized-package-management","headings":["Decentralized Package Management"],"excerpt":"Decentralized Package Management Unlike other tools, EasyP doesn't rely on a centralized server for package distribution. Instead, any Git repository can serve as a package source, giving you:","content":"Decentralized Package Management Unlike other tools, EasyP doesn't rely on a centralized server for package distribution. Instead, any Git repository can serve as a package source, giving you:"},{"id":"introduction/what-is::decentralized-package-management::16","title":"What is EasyP?","section":"Decentralized Package Management","path":"/docs/guide/introduction/what-is#decentralized-package-management","headings":["Decentralized Package Management"],"excerpt":"Decentralized Package Management **Flexibility and Control**: Use any Git hosting service (GitHub, GitLab, self-hosted) **No Vendor Lock-in**: Your dependencies aren't tied to a specific registry **Version Control**: Ful","content":"Decentralized Package Management **Flexibility and Control**: Use any Git hosting service (GitHub, GitLab, self-hosted) **No Vendor Lock-in**: Your dependencies aren't tied to a specific registry **Version Control**: Full Git history and branching for your proto dependencies **Enterprise-Friendly**: Works with private repositories and corporate Git infrastructure"},{"id":"introduction/what-is::seamless-migration-from-buf::17","title":"What is EasyP?","section":"Seamless Migration from Buf","path":"/docs/guide/introduction/what-is#seamless-migration-from-buf","headings":["Seamless Migration from Buf"],"excerpt":"Seamless Migration from Buf EasyP is designed with buf compatibility in mind:","content":"Seamless Migration from Buf EasyP is designed with buf compatibility in mind:"},{"id":"introduction/what-is::seamless-migration-from-buf::18","title":"What is EasyP?","section":"Seamless Migration from Buf","path":"/docs/guide/introduction/what-is#seamless-migration-from-buf","headings":["Seamless Migration from Buf"],"excerpt":"Seamless Migration from Buf **Compatible rule sets**: Uses the same linting rules as buf **Familiar configuration**: Similar YAML structure with enhanced features **Drop-in replacement**: Can often replace buf with minim","content":"Seamless Migration from Buf **Compatible rule sets**: Uses the same linting rules as buf **Familiar configuration**: Similar YAML structure with enhanced features **Drop-in replacement**: Can often replace buf with minimal configuration changes **Gradual migration**: Adopt EasyP features incrementally without disrupting existing workflows"},{"id":"introduction/what-is::easyp-vs-bufbuild-comparison::19","title":"What is EasyP?","section":"EasyP vs buf.build Comparison","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild-comparison","headings":["EasyP vs buf.build Comparison"],"excerpt":"EasyP vs buf.build Comparison Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git-based repositories Buf Schema Registry (BSR) **Vendor Lock-in** None - works with any Git hosting Tied to","content":"EasyP vs buf.build Comparison Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git-based repositories Buf Schema Registry (BSR) **Vendor Lock-in** None - works with any Git hosting Tied to BSR for full features **Plugin Execution** Local + Remote plugins Local + BSR plugins **Private Dependencies** Any Git provider (GitHub, GitLab, etc.) BSR or manual management **Offline Development** Full support with mod vendor Limited without BSR access **Enterprise Integration** Works with existing Git infrastructure Requires BSR setup **Breaking Change Detection** Against any Git reference Against any Git reference **Package Distribution** Any Git repository BSR required for publishing **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild-comparison::20","title":"What is EasyP?","section":"EasyP vs buf.build Comparison","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild-comparison","headings":["EasyP vs buf.build Comparison"],"excerpt":"EasyP vs buf.build Comparison **Migration Benefits:** **No infrastructure changes**: Continue using your existing Git repositories **Gradual adoption**: Start with EasyP while keeping existing buf configurations **Enhanc","content":"EasyP vs buf.build Comparison **Migration Benefits:** **No infrastructure changes**: Continue using your existing Git repositories **Gradual adoption**: Start with EasyP while keeping existing buf configurations **Enhanced flexibility**: Access to both local and remote plugin execution **Simplified workflows**: Single configuration file for all protobuf operations"},{"id":"introduction/what-is::our-goals-for-protobuf::21","title":"What is EasyP?","section":"Our Goals for Protobuf","path":"/docs/guide/introduction/what-is#our-goals-for-protobuf","headings":["Our Goals for Protobuf"],"excerpt":"Our Goals for Protobuf EasyP's mission is to accelerate the adoption of **schema-driven API development** by making Protocol Buffers more accessible and reliable:","content":"Our Goals for Protobuf EasyP's mission is to accelerate the adoption of **schema-driven API development** by making Protocol Buffers more accessible and reliable:"},{"id":"introduction/what-is::modern-protobuf-ecosystem::22","title":"What is EasyP?","section":"Modern Protobuf Ecosystem","path":"/docs/guide/introduction/what-is#modern-protobuf-ecosystem","headings":["Modern Protobuf Ecosystem"],"excerpt":"Modern Protobuf Ecosystem We're building on Protobuf's proven foundation to create a modern development experience that rivals the simplicity of REST/JSON while providing superior type safety and performance.","content":"Modern Protobuf Ecosystem We're building on Protobuf's proven foundation to create a modern development experience that rivals the simplicity of REST/JSON while providing superior type safety and performance."},{"id":"introduction/what-is::developer-experience-first::23","title":"What is EasyP?","section":"Developer Experience First","path":"/docs/guide/introduction/what-is#developer-experience-first","headings":["Developer Experience First"],"excerpt":"Developer Experience First Every feature is designed with developer productivity in mind, from intuitive CLI commands to comprehensive error messages and documentation.","content":"Developer Experience First Every feature is designed with developer productivity in mind, from intuitive CLI commands to comprehensive error messages and documentation."},{"id":"introduction/what-is::enterprise-ready::24","title":"What is EasyP?","section":"Enterprise Ready","path":"/docs/guide/introduction/what-is#enterprise-ready","headings":["Enterprise Ready"],"excerpt":"Enterprise Ready Built for teams and organizations with features like reproducible builds, private repository support, and comprehensive CI/CD integration.","content":"Enterprise Ready Built for teams and organizations with features like reproducible builds, private repository support, and comprehensive CI/CD integration."},{"id":"introduction/what-is::for-individual-developers::25","title":"What is EasyP?","section":"For Individual Developers","path":"/docs/guide/introduction/what-is#for-individual-developers","headings":["For Individual Developers"],"excerpt":"For Individual Developers **Quick Setup**: Get started with protobuf projects in minutes, not hours **Unified Workflow**: One tool for all your protobuf needs **Clear Documentation**: Comprehensive guides and examples","content":"For Individual Developers **Quick Setup**: Get started with protobuf projects in minutes, not hours **Unified Workflow**: One tool for all your protobuf needs **Clear Documentation**: Comprehensive guides and examples"},{"id":"introduction/what-is::for-teams::26","title":"What is EasyP?","section":"For Teams","path":"/docs/guide/introduction/what-is#for-teams","headings":["For Teams"],"excerpt":"For Teams **Consistent Standards**: Enforced linting rules and formatting across all projects **Reproducible Builds**: Lock files ensure everyone builds the same way **Easy Onboarding**: New team members can be productiv","content":"For Teams **Consistent Standards**: Enforced linting rules and formatting across all projects **Reproducible Builds**: Lock files ensure everyone builds the same way **Easy Onboarding**: New team members can be productive immediately"},{"id":"introduction/what-is::for-organizations::27","title":"What is EasyP?","section":"For Organizations","path":"/docs/guide/introduction/what-is#for-organizations","headings":["For Organizations"],"excerpt":"For Organizations **No Vendor Lock-in**: Git-based dependencies work with your existing infrastructure **Enterprise Security**: Support for private repositories and custom authentication **CI/CD Ready**: Designed for aut","content":"For Organizations **No Vendor Lock-in**: Git-based dependencies work with your existing infrastructure **Enterprise Security**: Support for private repositories and custom authentication **CI/CD Ready**: Designed for automated workflows and continuous integration"},{"id":"introduction/what-is::whats-next::28","title":"What is EasyP?","section":"What's Next?","path":"/docs/guide/introduction/what-is#whats-next","headings":["What's Next?"],"excerpt":"What's Next? EasyP simplifies protobuf development so you can focus on building great APIs instead of managing toolchain complexity. Whether you're starting a new project or migrating from existing tools, EasyP provides ","content":"What's Next? EasyP simplifies protobuf development so you can focus on building great APIs instead of managing toolchain complexity. Whether you're starting a new project or migrating from existing tools, EasyP provides a smooth path to modern protobuf development."},{"id":"introduction/what-is::whats-next::29","title":"What is EasyP?","section":"What's Next?","path":"/docs/guide/introduction/what-is#whats-next","headings":["What's Next?"],"excerpt":"What's Next? Ready to get started? Check out our Installation Guide and Quickstart Tutorial.","content":"What's Next? Ready to get started? Check out our Installation Guide and Quickstart Tutorial."},{"id":"introduction/what-is::stargazers-over-time::30","title":"What is EasyP?","section":"Stargazers over time","path":"/docs/guide/introduction/what-is#stargazers-over-time","headings":["Stargazers over time"],"excerpt":"Stargazers over time Stargazers over time","content":"Stargazers over time Stargazers over time"},{"id":"migration/buf-cli::top::0","title":"Buf CLI","path":"/docs/guide/migration/buf-cli","headings":[],"excerpt":"Buf CLI Work in progress","content":"Buf CLI Work in progress"},{"id":"migration/protoc::top::0","title":"Protoc","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Protoc Work in progress","content":"Protoc Work in progress"},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock Work in progress","content":"Protolock Work in progress"},{"id":"migration/prototool::top::0","title":"Prototool","path":"/docs/guide/migration/prototool","headings":[],"excerpt":"Prototool Work in progress","content":"Prototool Work in progress"}] \ No newline at end of file +[{"id":"api-service/overview::top::0","title":"API Service Overview","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"**Centralized protobuf plugin execution service for consistent, isolated code generation**","content":"**Centralized protobuf plugin execution service for consistent, isolated code generation**"},{"id":"api-service/overview::top::1","title":"API Service Overview","path":"/docs/guide/api-service/overview","headings":[],"excerpt":"The EasyP API Service eliminates plugin management chaos by providing centralized execution of protobuf/gRPC plugins as isolated Docker containers. It offers a unified platform for teams to standardize their code generat","content":"The EasyP API Service eliminates plugin management chaos by providing centralized execution of protobuf/gRPC plugins as isolated Docker containers. It offers a unified platform for teams to standardize their code generation workflows without the operational overhead of managing plugins across individual developer machines."},{"id":"api-service/overview::the-challenge::2","title":"API Service Overview","section":"The Challenge","path":"/docs/guide/api-service/overview#the-challenge","headings":["The Challenge"],"excerpt":"The Challenge Managing protobuf/gRPC code generation across development teams creates significant operational complexity:","content":"The Challenge Managing protobuf/gRPC code generation across development teams creates significant operational complexity:"},{"id":"api-service/overview::version-inconsistencies::3","title":"API Service Overview","section":"Version Inconsistencies","path":"/docs/guide/api-service/overview#version-inconsistencies","headings":["Version Inconsistencies"],"excerpt":"Version Inconsistencies Developers use different plugin versions locally, causing build failures and inconsistent generated code \"Works on my machine\" syndrome when generated code differs between environments Manual coor","content":"Version Inconsistencies Developers use different plugin versions locally, causing build failures and inconsistent generated code \"Works on my machine\" syndrome when generated code differs between environments Manual coordination required to keep entire teams synchronized on plugin versions"},{"id":"api-service/overview::operational-overhead::4","title":"API Service Overview","section":"Operational Overhead","path":"/docs/guide/api-service/overview#operational-overhead","headings":["Operational Overhead"],"excerpt":"Operational Overhead DevOps teams spend significant time managing plugin installations across developer machines Each new team member requires manual setup of correct plugin versions Plugin updates require coordinating w","content":"Operational Overhead DevOps teams spend significant time managing plugin installations across developer machines Each new team member requires manual setup of correct plugin versions Plugin updates require coordinating with every developer individually No centralized control over which plugin versions are approved for use"},{"id":"api-service/overview::security-compliance-risks::5","title":"API Service Overview","section":"Security & Compliance Risks","path":"/docs/guide/api-service/overview#security-compliance-risks","headings":["Security & Compliance Risks"],"excerpt":"Security & Compliance Risks Developers install plugins from various sources without security validation No audit trail of which plugins were used for which builds Difficult to enforce security policies on code generation","content":"Security & Compliance Risks Developers install plugins from various sources without security validation No audit trail of which plugins were used for which builds Difficult to enforce security policies on code generation tools"},{"id":"api-service/overview::the-solution-centralized-plugin-execution::6","title":"API Service Overview","section":"The Solution: Centralized Plugin Execution","path":"/docs/guide/api-service/overview#the-solution-centralized-plugin-execution","headings":["The Solution: Centralized Plugin Execution"],"excerpt":"The Solution: Centralized Plugin Execution EasyP API Service eliminates these operational headaches by centralizing plugin management:","content":"The Solution: Centralized Plugin Execution EasyP API Service eliminates these operational headaches by centralizing plugin management:"},{"id":"api-service/overview::the-solution-centralized-plugin-execution::7","title":"API Service Overview","section":"The Solution: Centralized Plugin Execution","path":"/docs/guide/api-service/overview#the-solution-centralized-plugin-execution","headings":["The Solution: Centralized Plugin Execution"],"excerpt":"The Solution: Centralized Plugin Execution Challenge Solution ----------- ---------- **Version Control** Deploy new plugin versions to entire team instantly via Docker images **Operations** Operations team controls plugi","content":"The Solution: Centralized Plugin Execution Challenge Solution ----------- ---------- **Version Control** Deploy new plugin versions to entire team instantly via Docker images **Operations** Operations team controls plugin configurations without touching developer machines **Security** All plugins run in isolated Docker containers with resource constraints **Consistency** Consistent execution environment regardless of developer's local setup **Developer Experience** No local plugin installation or maintenance required"},{"id":"api-service/overview::architecture-overview::8","title":"API Service Overview","section":"Architecture Overview","path":"/docs/guide/api-service/overview#architecture-overview","headings":["Architecture Overview"],"excerpt":"Architecture Overview The EasyP API Service uses a streamlined architecture focused on reliable plugin execution:","content":"Architecture Overview The EasyP API Service uses a streamlined architecture focused on reliable plugin execution:"},{"id":"api-service/overview::api-layer::9","title":"API Service Overview","section":"API Layer","path":"/docs/guide/api-service/overview#api-layer","headings":["API Layer"],"excerpt":"API Layer **gRPC Server**: Primary API for code generation requests Each plugin execution is a separate gRPC request Receives CodeGeneratorRequest from CLI","content":"API Layer **gRPC Server**: Primary API for code generation requests Each plugin execution is a separate gRPC request Receives CodeGeneratorRequest from CLI"},{"id":"api-service/overview::execution-engine::10","title":"API Service Overview","section":"Execution Engine","path":"/docs/guide/api-service/overview#execution-engine","headings":["Execution Engine"],"excerpt":"Execution Engine **Docker Runtime**: Isolated container execution for plugins Pulls plugin images from public Docker registries (Docker Hub, etc.) Enforces resource limits (CPU, memory) per plugin","content":"Execution Engine **Docker Runtime**: Isolated container execution for plugins Pulls plugin images from public Docker registries (Docker Hub, etc.) Enforces resource limits (CPU, memory) per plugin"},{"id":"api-service/overview::storage-layer::11","title":"API Service Overview","section":"Storage Layer","path":"/docs/guide/api-service/overview#storage-layer","headings":["Storage Layer"],"excerpt":"Storage Layer **PostgreSQL**: Stores plugin execution parameters - Resource limits (CPU, memory allocation) - Plugin configuration and metadata - Execution logs for auditing - _Note: Storage capabilities will be expanded","content":"Storage Layer **PostgreSQL**: Stores plugin execution parameters - Resource limits (CPU, memory allocation) - Plugin configuration and metadata - Execution logs for auditing - _Note: Storage capabilities will be expanded in future releases_"},{"id":"api-service/overview::monitoring::12","title":"API Service Overview","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus**: Metrics collection and monitoring Tracks execution times, success rates, and resource usage","content":"Monitoring **Prometheus**: Metrics collection and monitoring Tracks execution times, success rates, and resource usage"},{"id":"api-service/overview::local-execution-easyp-cli::13","title":"API Service Overview","section":"Local Execution (EasyP CLI)","path":"/docs/guide/api-service/overview#local-execution-easyp-cli","headings":["Local Execution (EasyP CLI)"],"excerpt":"Local Execution (EasyP CLI) When running locally, the EasyP CLI supports: **Installed plugins**: System-installed protoc plugins **WASM plugins**: Fast, lightweight WebAssembly plugins","content":"Local Execution (EasyP CLI) When running locally, the EasyP CLI supports: **Installed plugins**: System-installed protoc plugins **WASM plugins**: Fast, lightweight WebAssembly plugins"},{"id":"api-service/overview::remote-execution-api-service::14","title":"API Service Overview","section":"Remote Execution (API Service)","path":"/docs/guide/api-service/overview#remote-execution-api-service","headings":["Remote Execution (API Service)"],"excerpt":"Remote Execution (API Service) When using the API Service: **Docker only**: All plugins run as Docker containers **Centralized control**: Operations team manages available plugins **Consistent environment**: Same executi","content":"Remote Execution (API Service) When using the API Service: **Docker only**: All plugins run as Docker containers **Centralized control**: Operations team manages available plugins **Consistent environment**: Same execution environment for all developers"},{"id":"api-service/overview::execution-steps::15","title":"API Service Overview","section":"Execution Steps","path":"/docs/guide/api-service/overview#execution-steps","headings":["Execution Steps"],"excerpt":"Execution Steps **CLI Parsing**: CLI parses protobuf files locally **Request Sending**: CLI sends CodeGeneratorRequest to API Service (one request per plugin) **Parameter Lookup**: API Service fetches plugin execution pa","content":"Execution Steps **CLI Parsing**: CLI parses protobuf files locally **Request Sending**: CLI sends CodeGeneratorRequest to API Service (one request per plugin) **Parameter Lookup**: API Service fetches plugin execution parameters from PostgreSQL **Docker Execution**: API Service runs plugin in isolated Docker container **Metrics Recording**: Execution metrics are recorded (at end of request) **Response**: Generated code is returned to CLI"},{"id":"api-service/overview::key-features::16","title":"API Service Overview","section":"Key Features","path":"/docs/guide/api-service/overview#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- **🐳 Plugin Isolation** Each plugin runs in a secure, isolated Docker container **⚙️ Resource Control** CPU and memory limits enforced per plugin **📊 Metrics & Mo","content":"Key Features Feature Description --------- ------------- **🐳 Plugin Isolation** Each plugin runs in a secure, isolated Docker container **⚙️ Resource Control** CPU and memory limits enforced per plugin **📊 Metrics & Monitoring** Prometheus metrics for all operations **🔄 Version Management** Centralized plugin version control via Docker images **⚡ Simple Protocol** Standard CodeGeneratorRequest/Response protocol **🔒 Security First** Container isolation with resource constraints"},{"id":"api-service/overview::configuration::17","title":"API Service Overview","section":"Configuration","path":"/docs/guide/api-service/overview#configuration","headings":["Configuration"],"excerpt":"Configuration The service is configured via environment variables:","content":"Configuration The service is configured via environment variables:"},{"id":"api-service/overview::plugin-parameters-storage::18","title":"API Service Overview","section":"Plugin Parameters Storage","path":"/docs/guide/api-service/overview#plugin-parameters-storage","headings":["Plugin Parameters Storage"],"excerpt":"Plugin Parameters Storage PostgreSQL stores execution parameters for each plugin:","content":"Plugin Parameters Storage PostgreSQL stores execution parameters for each plugin:"},{"id":"api-service/overview::plugin-parameters-storage::19","title":"API Service Overview","section":"Plugin Parameters Storage","path":"/docs/guide/api-service/overview#plugin-parameters-storage","headings":["Plugin Parameters Storage"],"excerpt":"Plugin Parameters Storage ::: tip The storage schema and capabilities will be expanded in future releases to support additional features like audit logging, usage analytics, and plugin caching. :::","content":"Plugin Parameters Storage ::: tip The storage schema and capabilities will be expanded in future releases to support additional features like audit logging, usage analytics, and plugin caching. :::"},{"id":"api-service/overview::integration-with-easyp-cli::20","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI Configure your easyp.yaml to use remote plugin execution:","content":"Integration with EasyP CLI Configure your easyp.yaml to use remote plugin execution:"},{"id":"api-service/overview::integration-with-easyp-cli::21","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI Then generate code:","content":"Integration with EasyP CLI Then generate code:"},{"id":"api-service/overview::integration-with-easyp-cli::22","title":"API Service Overview","section":"Integration with EasyP CLI","path":"/docs/guide/api-service/overview#integration-with-easyp-cli","headings":["Integration with EasyP CLI"],"excerpt":"Integration with EasyP CLI The CLI will: Parse your protobuf files Send separate requests to API Service for each plugin Receive generated code responses Write generated files to specified output directories","content":"Integration with EasyP CLI The CLI will: Parse your protobuf files Send separate requests to API Service for each plugin Receive generated code responses Write generated files to specified output directories"},{"id":"api-service/overview::available-metrics::23","title":"API Service Overview","section":"Available Metrics","path":"/docs/guide/api-service/overview#available-metrics","headings":["Available Metrics"],"excerpt":"Available Metrics Prometheus metrics exposed by the service:","content":"Available Metrics Prometheus metrics exposed by the service:"},{"id":"api-service/overview::available-metrics::24","title":"API Service Overview","section":"Available Metrics","path":"/docs/guide/api-service/overview#available-metrics","headings":["Available Metrics"],"excerpt":"Available Metrics Metric Description -------- ------------- easyp_api_service_api_grpc_server_handled_total Total gRPC requests by status code easyp_api_service_api_grpc_server_handling_seconds gRPC request latency histo","content":"Available Metrics Metric Description -------- ------------- easyp_api_service_api_grpc_server_handled_total Total gRPC requests by status code easyp_api_service_api_grpc_server_handling_seconds gRPC request latency histogram easyp_api_service_generated_plugin_code_total Plugin executions by plugin name easyp_api_service_repo_call_duration_seconds Database query latency easyp_api_service_repo_errors_total Database errors count easyp_api_service_standard_panics_total Recovered panics count"},{"id":"api-service/overview::performance-characteristics::25","title":"API Service Overview","section":"Performance Characteristics","path":"/docs/guide/api-service/overview#performance-characteristics","headings":["Performance Characteristics"],"excerpt":"Performance Characteristics Metric Typical Value Notes -------- --------------- ------- **Cold Start** 2-5 seconds First time pulling plugin image **Warm Start** 100-500ms Plugin image cached by Docker **Throughput** 20-","content":"Performance Characteristics Metric Typical Value Notes -------- --------------- ------- **Cold Start** 2-5 seconds First time pulling plugin image **Warm Start** 100-500ms Plugin image cached by Docker **Throughput** 20-50 concurrent Depends on available resources **Memory Usage** 50-200MB Per plugin execution"},{"id":"api-service/overview::container-isolation::26","title":"API Service Overview","section":"Container Isolation","path":"/docs/guide/api-service/overview#container-isolation","headings":["Container Isolation"],"excerpt":"Container Isolation Each plugin runs in a separate, ephemeral container No network access during plugin execution Resource limits (CPU, memory) enforced via Docker Containers destroyed after execution","content":"Container Isolation Each plugin runs in a separate, ephemeral container No network access during plugin execution Resource limits (CPU, memory) enforced via Docker Containers destroyed after execution"},{"id":"api-service/overview::api-security::27","title":"API Service Overview","section":"API Security","path":"/docs/guide/api-service/overview#api-security","headings":["API Security"],"excerpt":"API Security gRPC-based communication Support for authentication tokens (production deployments) Input validation for all requests Execution audit logs stored in PostgreSQL","content":"API Security gRPC-based communication Support for authentication tokens (production deployments) Input validation for all requests Execution audit logs stored in PostgreSQL"},{"id":"api-service/overview::scalability::28","title":"API Service Overview","section":"Scalability","path":"/docs/guide/api-service/overview#scalability","headings":["Scalability"],"excerpt":"Scalability **Horizontal scaling**: Deploy multiple service instances behind load balancer **Resource management**: Configure appropriate CPU/memory limits per plugin **Database**: PostgreSQL can be replicated for high a","content":"Scalability **Horizontal scaling**: Deploy multiple service instances behind load balancer **Resource management**: Configure appropriate CPU/memory limits per plugin **Database**: PostgreSQL can be replicated for high availability"},{"id":"api-service/overview::monitoring::29","title":"API Service Overview","section":"Monitoring","path":"/docs/guide/api-service/overview#monitoring","headings":["Monitoring"],"excerpt":"Monitoring **Prometheus metrics**: Monitor all aspects of service health **Alerting**: Set up alerts for high error rates or slow execution **Logs**: Structured logging for debugging and audit trails","content":"Monitoring **Prometheus metrics**: Monitor all aspects of service health **Alerting**: Set up alerts for high error rates or slow execution **Logs**: Structured logging for debugging and audit trails"},{"id":"api-service/overview::future-enhancements::30","title":"API Service Overview","section":"Future Enhancements","path":"/docs/guide/api-service/overview#future-enhancements","headings":["Future Enhancements"],"excerpt":"Future Enhancements The API Service is actively developed with planned features including: Plugin result caching for faster repeated executions Enhanced audit logging and usage analytics Support for custom plugin registr","content":"Future Enhancements The API Service is actively developed with planned features including: Plugin result caching for faster repeated executions Enhanced audit logging and usage analytics Support for custom plugin registries Advanced resource scheduling and optimization"},{"id":"api-service/overview::community-and-support::31","title":"API Service Overview","section":"Community and Support","path":"/docs/guide/api-service/overview#community-and-support","headings":["Community and Support"],"excerpt":"Community and Support **💬 Telegram Chat** - Community discussion **🐛 GitHub Issues** - Bug reports and features **📖 Documentation** - Complete documentation","content":"Community and Support **💬 Telegram Chat** - Community discussion **🐛 GitHub Issues** - Bug reports and features **📖 Documentation** - Complete documentation"},{"id":"api-service/overview::community-and-support::32","title":"API Service Overview","section":"Community and Support","path":"/docs/guide/api-service/overview#community-and-support","headings":["Community and Support"],"excerpt":"Community and Support *Simplify your protobuf workflows with centralized plugin execution*","content":"Community and Support *Simplify your protobuf workflows with centralized plugin execution*"},{"id":"ci-cd/github-actions::top::0","title":"Github Actions","path":"/docs/guide/ci-cd/github-actions","headings":[],"excerpt":"Github Actions Work in progress","content":"Github Actions Work in progress"},{"id":"ci-cd/gitlab::top::0","title":"Gitlab","path":"/docs/guide/ci-cd/gitlab","headings":[],"excerpt":"Gitlab Work in progress","content":"Gitlab Work in progress"},{"id":"cli/auto-completion/auto-completion::zsh-auto-completion::0","title":"Auto completion","section":"zsh auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#zsh-auto-completion","headings":["zsh auto-completion"],"excerpt":"zsh auto-completion Add the following line to your ~/.zshrc startup script:","content":"zsh auto-completion Add the following line to your ~/.zshrc startup script:"},{"id":"cli/auto-completion/auto-completion::zsh-auto-completion::1","title":"Auto completion","section":"zsh auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#zsh-auto-completion","headings":["zsh auto-completion"],"excerpt":"zsh auto-completion Re-launch your shell or run:","content":"zsh auto-completion Re-launch your shell or run:"},{"id":"cli/auto-completion/auto-completion::bash-auto-completion::2","title":"Auto completion","section":"Bash auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#bash-auto-completion","headings":["Bash auto-completion"],"excerpt":"Bash auto-completion Install bash-completion and add the software to your ~/.bashrc. Add the following line to your ~/.bashrc startup script:","content":"Bash auto-completion Install bash-completion and add the software to your ~/.bashrc. Add the following line to your ~/.bashrc startup script:"},{"id":"cli/auto-completion/auto-completion::bash-auto-completion::3","title":"Auto completion","section":"Bash auto-completion","path":"/docs/guide/cli/auto-completion/auto-completion#bash-auto-completion","headings":["Bash auto-completion"],"excerpt":"Bash auto-completion Re-launch your shell or run:","content":"Bash auto-completion Re-launch your shell or run:"},{"id":"cli/breaking-changes/breaking-changes::top::0","title":"Breaking Changes Detection","path":"/docs/guide/cli/breaking-changes/breaking-changes","headings":[],"excerpt":"EasyP's breaking changes detection helps you maintain backward compatibility in your protobuf APIs by automatically identifying changes that could break existing clients. This is crucial for maintaining stable APIs in pr","content":"EasyP's breaking changes detection helps you maintain backward compatibility in your protobuf APIs by automatically identifying changes that could break existing clients. This is crucial for maintaining stable APIs in production environments."},{"id":"cli/breaking-changes/breaking-changes::overview::1","title":"Breaking Changes Detection","section":"Overview","path":"/docs/guide/cli/breaking-changes/breaking-changes#overview","headings":["Overview"],"excerpt":"Overview The breaking changes checker compares your current protobuf files against a previous version (typically from another Git branch) and identifies modifications that could cause compatibility issues for existing cl","content":"Overview The breaking changes checker compares your current protobuf files against a previous version (typically from another Git branch) and identifies modifications that could cause compatibility issues for existing clients."},{"id":"cli/breaking-changes/breaking-changes::key-features::2","title":"Breaking Changes Detection","section":"Key Features","path":"/docs/guide/cli/breaking-changes/breaking-changes#key-features","headings":["Key Features"],"excerpt":"Key Features **Git-based Comparison**: Compare against any Git reference (branch, tag, or commit) **Comprehensive Analysis**: Checks services, messages, enums, fields, and imports **Selective Ignore**: Skip specific dire","content":"Key Features **Git-based Comparison**: Compare against any Git reference (branch, tag, or commit) **Comprehensive Analysis**: Checks services, messages, enums, fields, and imports **Selective Ignore**: Skip specific directories from breaking change analysis **Detailed Reports**: Clear error messages with file locations and line numbers"},{"id":"cli/breaking-changes/breaking-changes::how-it-works::3","title":"Breaking Changes Detection","section":"How It Works","path":"/docs/guide/cli/breaking-changes/breaking-changes#how-it-works","headings":["How It Works"],"excerpt":"How It Works The breaking changes detector follows this process:","content":"How It Works The breaking changes detector follows this process:"},{"id":"cli/breaking-changes/breaking-changes::how-it-works::4","title":"Breaking Changes Detection","section":"How It Works","path":"/docs/guide/cli/breaking-changes/breaking-changes#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Checkout Comparison Branch**: Retrieves proto files from the specified Git reference **Parse Both Versions**: Analyzes current and previous proto file structures **Compare Entities**: Systematically checks","content":"How It Works **Checkout Comparison Branch**: Retrieves proto files from the specified Git reference **Parse Both Versions**: Analyzes current and previous proto file structures **Compare Entities**: Systematically checks all protobuf elements for breaking changes **Generate Report**: Produces detailed issue reports with locations and descriptions"},{"id":"cli/breaking-changes/breaking-changes::detection-level::5","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level EasyP implements **WIRE+ level** breaking change detection: ✅ **Full wire format compatibility** - ensures old and new versions can exchange data ✅ **Element deletion detection** - catches deleted service","content":"Detection Level EasyP implements **WIRE+ level** breaking change detection: ✅ **Full wire format compatibility** - ensures old and new versions can exchange data ✅ **Element deletion detection** - catches deleted services, messages, fields, etc. ✅ **Type safety** - detects incompatible type changes ❌ **Field/method renames** - currently not detected (planned for future releases) ❌ **File-level changes** - package moves, file options not checked yet"},{"id":"cli/breaking-changes/breaking-changes::detection-level::6","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level This provides strong compatibility guarantees while being less strict than some tools that check generated code compatibility.","content":"Detection Level This provides strong compatibility guarantees while being less strict than some tools that check generated code compatibility."},{"id":"cli/breaking-changes/breaking-changes::configuration::7","title":"Breaking Changes Detection","section":"Configuration","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration","headings":["Configuration"],"excerpt":"Configuration Configure breaking changes detection in your easyp.yaml:","content":"Configuration Configure breaking changes detection in your easyp.yaml:"},{"id":"cli/breaking-changes/breaking-changes::configuration::8","title":"Breaking Changes Detection","section":"Configuration","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration","headings":["Configuration"],"excerpt":"Configuration ```yaml breaking: # Git reference to compare against (branch, tag, or commit hash) against_git_ref: \"main\" # Directories to ignore during breaking changes analysis ignore: - \"experimental\" - \"internal/proto","content":"Configuration ```yaml breaking: # Git reference to compare against (branch, tag, or commit hash) against_git_ref: \"main\" # Directories to ignore during breaking changes analysis ignore: - \"experimental\" - \"internal/proto\" - \"vendor\""},{"id":"cli/breaking-changes/breaking-changes::configuration::9","title":"Breaking Changes Detection","section":"Configuration","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration","headings":["Configuration"],"excerpt":"Configuration Additional options to braking check use: - FILE ```","content":"Configuration Additional options to braking check use: - FILE ```"},{"id":"cli/breaking-changes/breaking-changes::configuration-options::10","title":"Breaking Changes Detection","section":"Configuration Options","path":"/docs/guide/cli/breaking-changes/breaking-changes#configuration-options","headings":["Configuration Options"],"excerpt":"Configuration Options Option Description Default Required ------------------- ---------------------------------------------- --------- ---------- against_git_ref Git reference to compare against \"master\" No ignore List o","content":"Configuration Options Option Description Default Required ------------------- ---------------------------------------------- --------- ---------- against_git_ref Git reference to compare against \"master\" No ignore List of directories to exclude from analysis [] No use List of braking check options [] No"},{"id":"cli/breaking-changes/breaking-changes::basic-usage::11","title":"Breaking Changes Detection","section":"Basic Usage","path":"/docs/guide/cli/breaking-changes/breaking-changes#basic-usage","headings":["Basic Usage"],"excerpt":"Basic Usage Compare current changes against the main branch:","content":"Basic Usage Compare current changes against the main branch:"},{"id":"cli/breaking-changes/breaking-changes::using-configuration-file::12","title":"Breaking Changes Detection","section":"Using Configuration File","path":"/docs/guide/cli/breaking-changes/breaking-changes#using-configuration-file","headings":["Using Configuration File"],"excerpt":"Using Configuration File With a custom configuration file:","content":"Using Configuration File With a custom configuration file:"},{"id":"cli/breaking-changes/breaking-changes::override-git-reference::13","title":"Breaking Changes Detection","section":"Override Git Reference","path":"/docs/guide/cli/breaking-changes/breaking-changes#override-git-reference","headings":["Override Git Reference"],"excerpt":"Override Git Reference Override the configured branch:","content":"Override Git Reference Override the configured branch:"},{"id":"cli/breaking-changes/breaking-changes::detection-level::14","title":"Breaking Changes Detection","section":"Detection Level","path":"/docs/guide/cli/breaking-changes/breaking-changes#detection-level","headings":["Detection Level"],"excerpt":"Detection Level EasyP currently implements **WIRE+ level** breaking change detection, which provides comprehensive wire format compatibility plus some generated code protections:","content":"Detection Level EasyP currently implements **WIRE+ level** breaking change detection, which provides comprehensive wire format compatibility plus some generated code protections:"},{"id":"cli/breaking-changes/breaking-changes::comparison-with-buf-categories::15","title":"Breaking Changes Detection","section":"Comparison with Buf Categories","path":"/docs/guide/cli/breaking-changes/breaking-changes#comparison-with-buf-categories","headings":["Comparison with Buf Categories"],"excerpt":"Comparison with Buf Categories Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletio","content":"Comparison with Buf Categories Check Type Buf WIRE Buf WIRE_JSON Buf FILE EasyP Current ------------ ---------- --------------- ---------- --------------- **Element Deletions** Service deletion ❌ ❌ ✅ ✅ RPC method deletion ❌ ❌ ✅ ✅ Message deletion ❌ ❌ ✅ ✅ Field deletion (by number) ✅ ✅ ✅ ✅ Enum deletion ❌ ❌ ✅ ✅ Enum value deletion ✅ ✅ ✅ ✅ OneOf deletion ❌ ❌ ✅ ✅ Import deletion ❌ ❌ ✅ ✅ **Type Changes** Field type change ✅ ✅ ✅ ✅ RPC request/response type ✅ ✅ ✅ ✅ Optional/required changes ✅ ✅ ✅ ✅ **Naming (Generated Code)** Field rename (same number) ❌ ✅ ✅ ❌ Enum value rename ❌ ✅ ✅ ✅ **File Structure** Package change ✅ ✅ ✅ ❌ File options (go_package, etc) ❌ ❌ ✅ ❌ Moving types between files ❌ ❌ ✅ ❌"},{"id":"cli/breaking-changes/breaking-changes::what-this-means::16","title":"Breaking Changes Detection","section":"What This Means","path":"/docs/guide/cli/breaking-changes/breaking-changes#what-this-means","headings":["What This Means"],"excerpt":"What This Means **✅ EasyP WILL detect:** All wire format breaking changes Deletion of services, methods, messages, fields Type changes that break serialization Enum value renames (same number, different name)","content":"What This Means **✅ EasyP WILL detect:** All wire format breaking changes Deletion of services, methods, messages, fields Type changes that break serialization Enum value renames (same number, different name)"},{"id":"cli/breaking-changes/breaking-changes::what-this-means::17","title":"Breaking Changes Detection","section":"What This Means","path":"/docs/guide/cli/breaking-changes/breaking-changes#what-this-means","headings":["What This Means"],"excerpt":"What This Means **❌ EasyP will NOT detect:** Field renames (same number, different name) Package name changes File option changes (go_package, java_package, etc.) Moving types between files in the same package","content":"What This Means **❌ EasyP will NOT detect:** Field renames (same number, different name) Package name changes File option changes (go_package, java_package, etc.) Moving types between files in the same package"},{"id":"cli/breaking-changes/breaking-changes::breaking-change-rules::18","title":"Breaking Changes Detection","section":"Breaking Change Rules","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-change-rules","headings":["Breaking Change Rules"],"excerpt":"Breaking Change Rules EasyP detects the following types of breaking changes:","content":"Breaking Change Rules EasyP detects the following types of breaking changes:"},{"id":"cli/breaking-changes/breaking-changes::comparison-with-other-tools::19","title":"Breaking Changes Detection","section":"Comparison with Other Tools","path":"/docs/guide/cli/breaking-changes/breaking-changes#comparison-with-other-tools","headings":["Comparison with Other Tools"],"excerpt":"Comparison with Other Tools Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Wire format compatibility only ✅ **Full support** **WIRE+** Wire + element deletion detection ","content":"Comparison with Other Tools Detection Level Description EasyP Support ---------------- ------------- --------------- **WIRE** Wire format compatibility only ✅ **Full support** **WIRE+** Wire + element deletion detection ✅ **Current level** **FILE** Generated code compatibility ✅ **Current level**"},{"id":"cli/breaking-changes/breaking-changes::breaking-change-rules::20","title":"Breaking Changes Detection","section":"Breaking Change Rules","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-change-rules","headings":["Breaking Change Rules"],"excerpt":"Breaking Change Rules EasyP detects the following categories of breaking changes. Each rule has detailed documentation with examples:","content":"Breaking Change Rules EasyP detects the following categories of breaking changes. Each rule has detailed documentation with examples:"},{"id":"cli/breaking-changes/breaking-changes::service-and-rpc-changes::21","title":"Breaking Changes Detection","section":"🚨 Service and RPC Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#service-and-rpc-changes","headings":["🚨 Service and RPC Changes"],"excerpt":"🚨 Service and RPC Changes Rule Description Status ------ ------------- --------- SERVICE_NO_DELETE Services cannot be deleted ✅ Implemented RPC_NO_DELETE RPC methods cannot be deleted ✅ Implemented RPC_SAME_REQUEST_TYPE","content":"🚨 Service and RPC Changes Rule Description Status ------ ------------- --------- SERVICE_NO_DELETE Services cannot be deleted ✅ Implemented RPC_NO_DELETE RPC methods cannot be deleted ✅ Implemented RPC_SAME_REQUEST_TYPE RPC request types cannot be changed ✅ Implemented RPC_SAME_RESPONSE_TYPE RPC response types cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::message-and-field-changes::22","title":"Breaking Changes Detection","section":"📦 Message and Field Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#message-and-field-changes","headings":["📦 Message and Field Changes"],"excerpt":"📦 Message and Field Changes Rule Description Status ------ ------------- --------- MESSAGE_NO_DELETE Messages cannot be deleted ✅ Implemented FIELD_NO_DELETE Fields cannot be deleted ✅ Implemented FIELD_SAME_TYPE Field ","content":"📦 Message and Field Changes Rule Description Status ------ ------------- --------- MESSAGE_NO_DELETE Messages cannot be deleted ✅ Implemented FIELD_NO_DELETE Fields cannot be deleted ✅ Implemented FIELD_SAME_TYPE Field types cannot be changed ✅ Implemented FIELD_SAME_CARDINALITY Field optionality (optional/required) cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::enum-changes::23","title":"Breaking Changes Detection","section":"🔢 Enum Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#enum-changes","headings":["🔢 Enum Changes"],"excerpt":"🔢 Enum Changes Rule Description Status ------ ------------- --------- ENUM_NO_DELETE Enums cannot be deleted ✅ Implemented ENUM_VALUE_NO_DELETE Enum values cannot be deleted ✅ Implemented ENUM_VALUE_SAME_NAME Enum value","content":"🔢 Enum Changes Rule Description Status ------ ------------- --------- ENUM_NO_DELETE Enums cannot be deleted ✅ Implemented ENUM_VALUE_NO_DELETE Enum values cannot be deleted ✅ Implemented ENUM_VALUE_SAME_NAME Enum value names cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::oneof-changes::24","title":"Breaking Changes Detection","section":"🔗 OneOf Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#oneof-changes","headings":["🔗 OneOf Changes"],"excerpt":"🔗 OneOf Changes Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIELD_","content":"🔗 OneOf Changes Rule Description Status ------ ------------- --------- ONEOF_NO_DELETE OneOf fields cannot be deleted ✅ Implemented ONEOF_FIELD_NO_DELETE Fields within oneofs cannot be deleted ✅ Implemented ONEOF_FIELD_SAME_TYPE OneOf field types cannot be changed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::import-changes::25","title":"Breaking Changes Detection","section":"📥 Import Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#import-changes","headings":["📥 Import Changes"],"excerpt":"📥 Import Changes Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented","content":"📥 Import Changes Rule Description Status ------ ------------- --------- IMPORT_NO_DELETE Import statements cannot be removed ✅ Implemented"},{"id":"cli/breaking-changes/breaking-changes::not-currently-detected::26","title":"Breaking Changes Detection","section":"Not Currently Detected","path":"/docs/guide/cli/breaking-changes/breaking-changes#not-currently-detected","headings":["Not Currently Detected"],"excerpt":"Not Currently Detected The following changes are **NOT detected** by EasyP (but may break generated code):","content":"Not Currently Detected The following changes are **NOT detected** by EasyP (but may break generated code):"},{"id":"cli/breaking-changes/breaking-changes::not-currently-detected::27","title":"Breaking Changes Detection","section":"Not Currently Detected","path":"/docs/guide/cli/breaking-changes/breaking-changes#not-currently-detected","headings":["Not Currently Detected"],"excerpt":"Not Currently Detected Change Type Example Impact ------------- --------- --------- Field renaming string name = 1 → string full_name = 1 Generated code breaks Package changes package v1 → package v2 Import paths change ","content":"Not Currently Detected Change Type Example Impact ------------- --------- --------- Field renaming string name = 1 → string full_name = 1 Generated code breaks Package changes package v1 → package v2 Import paths change File options option go_package = \"old\" → option go_package = \"new\" Generated code location Moving between files Message moved to different .proto file Import dependencies"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::28","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation For comprehensive examples and migration strategies, see the individual rule documentation:","content":"Detailed Rules Documentation For comprehensive examples and migration strategies, see the individual rule documentation:"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::29","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation **Service Changes**: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE **Message Changes**: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDI","content":"Detailed Rules Documentation **Service Changes**: SERVICE_NO_DELETE, RPC_NO_DELETE, RPC_SAME_REQUEST_TYPE, RPC_SAME_RESPONSE_TYPE **Message Changes**: MESSAGE_NO_DELETE, FIELD_NO_DELETE, FIELD_SAME_TYPE, FIELD_SAME_CARDINALITY **Enum Changes**: ENUM_NO_DELETE, ENUM_VALUE_NO_DELETE, ENUM_VALUE_SAME_NAME **OneOf Changes**: ONEOF_NO_DELETE, ONEOF_FIELD_NO_DELETE, ONEOF_FIELD_SAME_TYPE **Import Changes**: IMPORT_NO_DELETE"},{"id":"cli/breaking-changes/breaking-changes::detailed-rules-documentation::30","title":"Breaking Changes Detection","section":"Detailed Rules Documentation","path":"/docs/guide/cli/breaking-changes/breaking-changes#detailed-rules-documentation","headings":["Detailed Rules Documentation"],"excerpt":"Detailed Rules Documentation Each rule includes: ❌ **Bad examples** with actual breaking changes ✅ **Good alternatives** showing safe approaches 🔧 **Migration strategies** for handling necessary changes 📋 **Real error ","content":"Detailed Rules Documentation Each rule includes: ❌ **Bad examples** with actual breaking changes ✅ **Good alternatives** showing safe approaches 🔧 **Migration strategies** for handling necessary changes 📋 **Real error messages** from EasyP"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::31","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) ```proto // Adding new elements is always safe message User { string name = 1; string email = 2; string phone = 3; // ✅ New field - safe }","content":"✅ Safe Changes (Always Allowed) ```proto // Adding new elements is always safe message User { string name = 1; string email = 2; string phone = 3; // ✅ New field - safe }"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::32","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ New RPC - safe }","content":"✅ Safe Changes (Always Allowed) service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc GetUserProfile(GetUserRequest) returns (UserProfile); // ✅ New RPC - safe }"},{"id":"cli/breaking-changes/breaking-changes::safe-changes-always-allowed::33","title":"Breaking Changes Detection","section":"✅ Safe Changes (Always Allowed)","path":"/docs/guide/cli/breaking-changes/breaking-changes#safe-changes-always-allowed","headings":["✅ Safe Changes (Always Allowed)"],"excerpt":"✅ Safe Changes (Always Allowed) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ New enum value - safe } ```","content":"✅ Safe Changes (Always Allowed) enum Status { STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; STATUS_PENDING = 2; // ✅ New enum value - safe } ```"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes-always-detected::34","title":"Breaking Changes Detection","section":"❌ Breaking Changes (Always Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes-always-detected","headings":["❌ Breaking Changes (Always Detected)"],"excerpt":"❌ Breaking Changes (Always Detected) ```proto // Deletions and type changes break compatibility message User { string name = 1; // ❌ Deleted field - BREAKING }","content":"❌ Breaking Changes (Always Detected) ```proto // Deletions and type changes break compatibility message User { string name = 1; // ❌ Deleted field - BREAKING }"},{"id":"cli/breaking-changes/breaking-changes::breaking-changes-always-detected::35","title":"Breaking Changes Detection","section":"❌ Breaking Changes (Always Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#breaking-changes-always-detected","headings":["❌ Breaking Changes (Always Detected)"],"excerpt":"❌ Breaking Changes (Always Detected) service UserService { // ❌ Deleted RPC method - BREAKING rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Changed request type - BREAKING } ```","content":"❌ Breaking Changes (Always Detected) service UserService { // ❌ Deleted RPC method - BREAKING rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // ❌ Changed request type - BREAKING } ```"},{"id":"cli/breaking-changes/breaking-changes::scenario-3-breaking-changes-currently-not-detected::36","title":"Breaking Changes Detection","section":"Scenario 3: Breaking Changes (Currently Not Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#scenario-3-breaking-changes-currently-not-detected","headings":["Scenario 3: Breaking Changes (Currently Not Detected)"],"excerpt":"Scenario 3: Breaking Changes (Currently Not Detected) ```proto // 🟡 Breaks generated code but passes EasyP checks message User { string user_name = 1; // Renamed from \"name\" string user_email = 2; // Renamed from \"email","content":"Scenario 3: Breaking Changes (Currently Not Detected) ```proto // 🟡 Breaks generated code but passes EasyP checks message User { string user_name = 1; // Renamed from \"name\" string user_email = 2; // Renamed from \"email\" }"},{"id":"cli/breaking-changes/breaking-changes::scenario-3-breaking-changes-currently-not-detected::37","title":"Breaking Changes Detection","section":"Scenario 3: Breaking Changes (Currently Not Detected)","path":"/docs/guide/cli/breaking-changes/breaking-changes#scenario-3-breaking-changes-currently-not-detected","headings":["Scenario 3: Breaking Changes (Currently Not Detected)"],"excerpt":"Scenario 3: Breaking Changes (Currently Not Detected) service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Renamed from GetUser } ```","content":"Scenario 3: Breaking Changes (Currently Not Detected) service UserService { rpc GetUserProfile(GetUserRequest) returns (GetUserResponse); // Renamed from GetUser } ```"},{"id":"cli/breaking-changes/breaking-changes::1-regular-checks::38","title":"Breaking Changes Detection","section":"1. Regular Checks","path":"/docs/guide/cli/breaking-changes/breaking-changes#1-regular-checks","headings":["1. Regular Checks"],"excerpt":"Regular Checks Run breaking change detection in your CI/CD pipeline:","content":"Regular Checks Run breaking change detection in your CI/CD pipeline:"},{"id":"cli/breaking-changes/breaking-changes::2-branch-protection::39","title":"Breaking Changes Detection","section":"2. Branch Protection","path":"/docs/guide/cli/breaking-changes/breaking-changes#2-branch-protection","headings":["2. Branch Protection"],"excerpt":"Branch Protection Use breaking change checks to protect important branches:","content":"Branch Protection Use breaking change checks to protect important branches:"},{"id":"cli/breaking-changes/breaking-changes::3-versioning-strategy::40","title":"Breaking Changes Detection","section":"3. Versioning Strategy","path":"/docs/guide/cli/breaking-changes/breaking-changes#3-versioning-strategy","headings":["3. Versioning Strategy"],"excerpt":"Versioning Strategy When breaking changes are necessary:","content":"Versioning Strategy When breaking changes are necessary:"},{"id":"cli/breaking-changes/breaking-changes::3-versioning-strategy::41","title":"Breaking Changes Detection","section":"3. Versioning Strategy","path":"/docs/guide/cli/breaking-changes/breaking-changes#3-versioning-strategy","headings":["3. Versioning Strategy"],"excerpt":"Versioning Strategy Create a new package version (e.g., myservice.v2) Maintain the old version during migration period Use deprecation notices in the old version","content":"Versioning Strategy Create a new package version (e.g., myservice.v2) Maintain the old version during migration period Use deprecation notices in the old version"},{"id":"cli/breaking-changes/breaking-changes::4-ignore-patterns::42","title":"Breaking Changes Detection","section":"4. Ignore Patterns","path":"/docs/guide/cli/breaking-changes/breaking-changes#4-ignore-patterns","headings":["4. Ignore Patterns"],"excerpt":"Ignore Patterns Use ignore patterns wisely:","content":"Ignore Patterns Use ignore patterns wisely:"},{"id":"cli/breaking-changes/breaking-changes::issue-repository-does-not-exist::43","title":"Breaking Changes Detection","section":"Issue: \"Repository does not exist\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-repository-does-not-exist","headings":["Issue: \"Repository does not exist\""],"excerpt":"Issue: \"Repository does not exist\" **Solution**: Ensure you're running the command in a Git repository with the specified branch available.","content":"Issue: \"Repository does not exist\" **Solution**: Ensure you're running the command in a Git repository with the specified branch available."},{"id":"cli/breaking-changes/breaking-changes::issue-cannot-find-git-ref::44","title":"Breaking Changes Detection","section":"Issue: \"Cannot find git ref\"","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-cannot-find-git-ref","headings":["Issue: \"Cannot find git ref\""],"excerpt":"Issue: \"Cannot find git ref\" **Solution**: Verify the branch/tag name exists and is accessible:","content":"Issue: \"Cannot find git ref\" **Solution**: Verify the branch/tag name exists and is accessible:"},{"id":"cli/breaking-changes/breaking-changes::issue-false-positives-in-generated-code::45","title":"Breaking Changes Detection","section":"Issue: False Positives in Generated Code","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-false-positives-in-generated-code","headings":["Issue: False Positives in Generated Code"],"excerpt":"Issue: False Positives in Generated Code **Solution**: Add generated directories to ignore list:","content":"Issue: False Positives in Generated Code **Solution**: Add generated directories to ignore list:"},{"id":"cli/breaking-changes/breaking-changes::issue-large-number-of-changes::46","title":"Breaking Changes Detection","section":"Issue: Large Number of Changes","path":"/docs/guide/cli/breaking-changes/breaking-changes#issue-large-number-of-changes","headings":["Issue: Large Number of Changes"],"excerpt":"Issue: Large Number of Changes **Solution**: For major refactoring, consider: Creating a new API version Implementing changes incrementally Using feature flags for gradual rollout","content":"Issue: Large Number of Changes **Solution**: For major refactoring, consider: Creating a new API version Implementing changes incrementally Using feature flags for gradual rollout"},{"id":"cli/breaking-changes/breaking-changes::github-actions::47","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions ```yaml name: API Compatibility Check","content":"GitHub Actions ```yaml name: API Compatibility Check"},{"id":"cli/breaking-changes/breaking-changes::github-actions::48","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions on: pull_request: branches: [ main ]","content":"GitHub Actions on: pull_request: branches: [ main ]"},{"id":"cli/breaking-changes/breaking-changes::github-actions::49","title":"Breaking Changes Detection","section":"GitHub Actions","path":"/docs/guide/cli/breaking-changes/breaking-changes#github-actions","headings":["GitHub Actions"],"excerpt":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Fetch full history - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tec","content":"GitHub Actions jobs: breaking-changes: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0 # Fetch full history - name: Install EasyP run: curl -sSfL https://raw.githubusercontent.com/easyp-tech/easyp/main/install.sh sh - name: Check for breaking changes run: ./bin/easyp breaking --against origin/main ```"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::50","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook ```bash #!/bin/sh .git/hooks/pre-push","content":"Pre-commit Hook ```bash #!/bin/sh .git/hooks/pre-push"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::51","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')","content":"Pre-commit Hook protected_branch='main' current_branch=$(git symbolic-ref HEAD sed -e 's,.*/\\(.*\\),\\1,')"},{"id":"cli/breaking-changes/breaking-changes::pre-commit-hook::52","title":"Breaking Changes Detection","section":"Pre-commit Hook","path":"/docs/guide/cli/breaking-changes/breaking-changes#pre-commit-hook","headings":["Pre-commit Hook"],"excerpt":"Pre-commit Hook if [ $current_branch = $protected_branch ]; then echo \"Running breaking changes check...\" easyp breaking --against HEAD~1 if [ $? -eq 1 ]; then echo \"❌ Breaking changes detected. Push rejected.\" exit 1 fi","content":"Pre-commit Hook if [ $current_branch = $protected_branch ]; then echo \"Running breaking changes check...\" easyp breaking --against HEAD~1 if [ $? -eq 1 ]; then echo \"❌ Breaking changes detected. Push rejected.\" exit 1 fi echo \"✅ No breaking changes detected.\" fi ```"},{"id":"cli/breaking-changes/breaking-changes::debug-mode::53","title":"Breaking Changes Detection","section":"Debug Mode","path":"/docs/guide/cli/breaking-changes/breaking-changes#debug-mode","headings":["Debug Mode"],"excerpt":"Debug Mode Enable debug logging for detailed information:","content":"Debug Mode Enable debug logging for detailed information:"},{"id":"cli/breaking-changes/breaking-changes::manual-comparison::54","title":"Breaking Changes Detection","section":"Manual Comparison","path":"/docs/guide/cli/breaking-changes/breaking-changes#manual-comparison","headings":["Manual Comparison"],"excerpt":"Manual Comparison For complex cases, you can manually inspect the comparison:","content":"Manual Comparison For complex cases, you can manually inspect the comparison:"},{"id":"cli/breaking-changes/breaking-changes::performance-optimization::55","title":"Breaking Changes Detection","section":"Performance Optimization","path":"/docs/guide/cli/breaking-changes/breaking-changes#performance-optimization","headings":["Performance Optimization"],"excerpt":"Performance Optimization For large repositories:","content":"Performance Optimization For large repositories:"},{"id":"cli/breaking-changes/breaking-changes::performance-optimization::56","title":"Breaking Changes Detection","section":"Performance Optimization","path":"/docs/guide/cli/breaking-changes/breaking-changes#performance-optimization","headings":["Performance Optimization"],"excerpt":"Performance Optimization The breaking changes detection in EasyP provides a robust foundation for maintaining API compatibility while allowing your protobuf schemas to evolve safely over time.","content":"Performance Optimization The breaking changes detection in EasyP provides a robust foundation for maintaining API compatibility while allowing your protobuf schemas to evolve safely over time."},{"id":"cli/breaking-changes/rules/enum-no-delete::top::0","title":"ENUM_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete","headings":[],"excerpt":"This rule checks that no enums are deleted from proto files. Deleting an enum breaks both wire format compatibility and generated code, as existing data may contain values from the deleted enum and client code depends on","content":"This rule checks that no enums are deleted from proto files. Deleting an enum breaks both wire format compatibility and generated code, as existing data may contain values from the deleted enum and client code depends on the generated enum types."},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::1","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::2","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::3","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]","content":"Bad enum UserRole { // [!code --] USER_ROLE_UNSPECIFIED = 0; // [!code --] USER_ROLE_ADMIN = 1; // [!code --] USER_ROLE_USER = 2; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::4","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```","content":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::5","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::6","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::7","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad // UserRole enum was deleted - BREAKING CHANGE!","content":"Bad // UserRole enum was deleted - BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/enum-no-delete::bad::8","title":"ENUM_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole no longer exists! } ```","content":"Bad message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3; // ERROR: UserRole no longer exists! } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::9","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested enum deletion:**","content":"More Examples **Nested enum deletion:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::10","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --] STATUS_INACTIVE = 2; // [!code --] } ","content":"More Examples ```proto // Before message User { string name = 1; Status status = 2; enum Status { // [!code --] STATUS_UNSPECIFIED = 0; // [!code --] STATUS_ACTIVE = 1; // [!code --] STATUS_INACTIVE = 2; // [!code --] } // [!code --] }"},{"id":"cli/breaking-changes/rules/enum-no-delete::more-examples::11","title":"ENUM_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status enum deleted // Status nested enum was deleted } ```","content":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Status status = 2; // ERROR: Status enum deleted // Status nested enum was deleted } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::12","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the enum:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::13","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::14","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Good enum UserRole { option deprecated = true; // [!code focus] USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::15","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```","content":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::16","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new enum:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new enum:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::17","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::18","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserRole { option deprecated = true; // [!code focus] // Old enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }","content":"Good enum UserRole { option deprecated = true; // [!code focus] // Old enum USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_USER = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::19","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good enum UserPermission { // [!code focus] // New enum with better design USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PER","content":"Good enum UserPermission { // [!code focus] // New enum with better design USER_PERMISSION_UNSPECIFIED = 0; // [!code focus] USER_PERMISSION_READ = 1; // [!code focus] USER_PERMISSION_WRITE = 2; // [!code focus] USER_PERMISSION_ADMIN = 3; // [!code focus] } // [!code focus]"},{"id":"cli/breaking-changes/rules/enum-no-delete::good::20","title":"ENUM_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] // Old field UserPermission created_by_permission = 4; // [!code focus] // New field } ```","content":"Good message Order { string id = 1; OrderStatus status = 2; UserRole created_by_role = 3 [deprecated = true]; // [!code focus] // Old field UserPermission created_by_permission = 4; // [!code focus] // New field } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::impact::21","title":"ENUM_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with the deleted enum cannot be deserialized **Generated Code:** Enum types/constants are removed, breaking client compilation **Field References:** Fields using the deleted enum typ","content":"Impact **Wire Format:** Existing data with the deleted enum cannot be deserialized **Generated Code:** Enum types/constants are removed, breaking client compilation **Field References:** Fields using the deleted enum type become invalid **Switch Statements:** Client code with enum switch cases breaks"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::22","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR ","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", Status: myapi.OrderStatus_ORDER_STATUS_PENDING, CreatedByRole: myapi.UserRole_USER_ROLE_ADMIN, // ERROR after deletion }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::23","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check role switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR: undefined type // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR: undefined type // User logic }","content":"Real-World Example // Check role switch order.CreatedByRole { case myapi.UserRole_USER_ROLE_ADMIN: // ERROR: undefined type // Admin logic case myapi.UserRole_USER_ROLE_USER: // ERROR: undefined type // User logic }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::24","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.UserRole // undefined: myapi.UserRole_USER_ROLE_ADMIN ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::25","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_PENDING\", \"created_by_role\": \"USER_ROLE_ADMIN\" }","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_PENDING\", \"created_by_role\": \"USER_ROLE_ADMIN\" }"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::26","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After UserRole deletion - deserialization fails // Parser doesn't know how to handle \"created_by_role\" field ```","content":"Real-World Example // After UserRole deletion - deserialization fails // Parser doesn't know how to handle \"created_by_role\" field ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::real-world-example::27","title":"ENUM_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:**","content":"Real-World Example **Server implementation breaks:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::28","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the enum first:**","content":"Migration Strategy **Deprecate the enum first:**"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::29","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using in new fields** and deprecate existing fields:","content":"Migration Strategy **Stop using in new fields** and deprecate existing fields:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::30","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create replacement** if needed:","content":"Migration Strategy **Create replacement** if needed:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::31","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both during transition:","content":"Migration Strategy **Update server code** to handle both during transition:"},{"id":"cli/breaking-changes/rules/enum-no-delete::migration-strategy::32","title":"ENUM_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum-redesign::33","title":"ENUM_NO_DELETE","section":"Enum Redesign","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum-redesign","headings":["Enum Redesign"],"excerpt":"Enum Redesign ```proto // Instead of deleting old enum enum Priority { option deprecated = true; // Deprecate old design PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }","content":"Enum Redesign ```proto // Instead of deleting old enum enum Priority { option deprecated = true; // Deprecate old design PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_HIGH = 2; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::enum-redesign::34","title":"ENUM_NO_DELETE","section":"Enum Redesign","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#enum-redesign","headings":["Enum Redesign"],"excerpt":"Enum Redesign enum TaskPriority { // Create new enum with better naming TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```","content":"Enum Redesign enum TaskPriority { // Create new enum with better naming TASK_PRIORITY_UNSPECIFIED = 0; TASK_PRIORITY_LOW = 1; TASK_PRIORITY_MEDIUM = 2; TASK_PRIORITY_HIGH = 3; TASK_PRIORITY_URGENT = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::35","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums ```proto // Instead of deleting multiple enums enum Status { option deprecated = true; // Keep old enum STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }","content":"Consolidating Enums ```proto // Instead of deleting multiple enums enum Status { option deprecated = true; // Keep old enum STATUS_UNSPECIFIED = 0; STATUS_ACTIVE = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::36","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums enum State { option deprecated = true; // Keep old enum STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }","content":"Consolidating Enums enum State { option deprecated = true; // Keep old enum STATE_UNSPECIFIED = 0; STATE_ENABLED = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::consolidating-enums::37","title":"ENUM_NO_DELETE","section":"Consolidating Enums","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#consolidating-enums","headings":["Consolidating Enums"],"excerpt":"Consolidating Enums enum EntityStatus { // New consolidated enum ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```","content":"Consolidating Enums enum EntityStatus { // New consolidated enum ENTITY_STATUS_UNSPECIFIED = 0; ENTITY_STATUS_ACTIVE = 1; ENTITY_STATUS_INACTIVE = 2; ENTITY_STATUS_ENABLED = 3; ENTITY_STATUS_DISABLED = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::38","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package ```proto // Instead of deleting from current package enum UserRole { option deprecated = true; // Mark as deprecated USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }","content":"Moving Enum to Different Package ```proto // Instead of deleting from current package enum UserRole { option deprecated = true; // Mark as deprecated USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::39","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package // Import from new location import \"common/roles.proto\";","content":"Moving Enum to Different Package // Import from new location import \"common/roles.proto\";"},{"id":"cli/breaking-changes/rules/enum-no-delete::moving-enum-to-different-package::40","title":"ENUM_NO_DELETE","section":"Moving Enum to Different Package","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#moving-enum-to-different-package","headings":["Moving Enum to Different Package"],"excerpt":"Moving Enum to Different Package message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; // Reference from new package } ```","content":"Moving Enum to Different Package message Order { UserRole old_role = 3 [deprecated = true]; common.UserRole new_role = 4; // Reference from new package } ```"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::41","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration ```proto // Clean approach - new package version package myapi.v2;","content":"Version Migration ```proto // Clean approach - new package version package myapi.v2;"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::42","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration // Redesigned enums without deprecated ones enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }","content":"Version Migration // Redesigned enums without deprecated ones enum UserPermission { USER_PERMISSION_UNSPECIFIED = 0; USER_PERMISSION_READ = 1; USER_PERMISSION_WRITE = 2; USER_PERMISSION_ADMIN = 3; }"},{"id":"cli/breaking-changes/rules/enum-no-delete::version-migration::43","title":"ENUM_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/enum-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration message Order { string id = 1; UserPermission created_by_permission = 2; // Clean design in v2 } ```","content":"Version Migration message Order { string id = 1; UserPermission created_by_permission = 2; // Clean design in v2 } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::top::0","title":"ENUM_VALUE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete","headings":[],"excerpt":"This rule checks that no enum values are deleted from enums. Deleting an enum value breaks both wire format compatibility and generated code, as existing data may contain the deleted enum value and client code may refere","content":"This rule checks that no enum values are deleted from enums. Deleting an enum value breaks both wire format compatibility and generated code, as existing data may contain the deleted enum value and client code may reference the generated constants."},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::1","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::2","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; }","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::3","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```","content":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::4","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::5","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; // ORDER_STATUS_CANCELLED = 5; // [!code --] Deleted enum v","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; // ORDER_STATUS_CANCELLED = 5; // [!code --] Deleted enum value - BREAKING! }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::bad::6","title":"ENUM_VALUE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#bad","headings":["Bad"],"excerpt":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Deleted enum value - BREAKING! } ```","content":"Bad enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; // PRIORITY_URGENT = 4; // [!code --] Deleted enum value - BREAKING! } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::7","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Multiple value deletions:**","content":"More Examples **Multiple value deletions:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::8","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_GUEST = 1; USER_ROLE_USER = 2; USER_ROLE_MODERATOR = 3; USER_ROLE_ADMIN = 4; USER_ROLE_SUPERADMIN = 5; }","content":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_GUEST = 1; USER_ROLE_USER = 2; USER_ROLE_MODERATOR = 3; USER_ROLE_ADMIN = 4; USER_ROLE_SUPERADMIN = 5; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::more-examples::9","title":"ENUM_VALUE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_USER = 2; USER_ROLE_ADMIN = 4; // USER_ROLE_GUEST = 1; // BREAKING: deleted // USER_ROLE_MODERATOR = 3; // BREAKING: deleted","content":"More Examples // After - BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_USER = 2; USER_ROLE_ADMIN = 4; // USER_ROLE_GUEST = 1; // BREAKING: deleted // USER_ROLE_MODERATOR = 3; // BREAKING: deleted // USER_ROLE_SUPERADMIN = 5; // BREAKING: deleted } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::10","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the enum values:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the enum values:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::11","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5 [deprecated = true]; // [!code ","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::12","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```","content":"Good enum Priority { PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; PRIORITY_URGENT = 4 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::13","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good **Or reserve the enum values after removal:** ```proto syntax = \"proto3\";","content":"Good **Or reserve the enum values after removal:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::14","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus] ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER","content":"Good enum OrderStatus { reserved 5; // [!code focus] reserved \"ORDER_STATUS_CANCELLED\"; // [!code focus] ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::good::15","title":"ENUM_VALUE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#good","headings":["Good"],"excerpt":"Good enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus] PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```","content":"Good enum Priority { reserved 4; // [!code focus] reserved \"PRIORITY_URGENT\"; // [!code focus] PRIORITY_UNSPECIFIED = 0; PRIORITY_LOW = 1; PRIORITY_MEDIUM = 2; PRIORITY_HIGH = 3; } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::impact::16","title":"ENUM_VALUE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with deleted enum values cannot be properly deserialized **Generated Code:** Enum constants are removed, breaking client compilation **Client Applications:** Code referencing deleted","content":"Impact **Wire Format:** Existing data with deleted enum values cannot be properly deserialized **Generated Code:** Enum constants are removed, breaking client compilation **Client Applications:** Code referencing deleted enum values fails to compile **Switch Statements:** Case statements for deleted values cause compilation errors **Default Handling:** Unknown enum values may be handled differently"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::17","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR after deletion }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Status: myapi.OrderStatus_ORDER_STATUS_CANCELLED, // ERROR after deletion }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::18","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch statement breaks switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Handle pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined constant // Handle can","content":"Real-World Example // Switch statement breaks switch order.Status { case myapi.OrderStatus_ORDER_STATUS_PENDING: // Handle pending case myapi.OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined constant // Handle cancellation default: // Handle unknown }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::19","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.OrderStatus_ORDER_STATUS_CANCELLED ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::20","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes problematic:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_CANCELLED\" }","content":"Real-World Example **Existing data becomes problematic:** ```json // Serialized data before deletion { \"id\": \"order123\", \"status\": \"ORDER_STATUS_CANCELLED\" }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::21","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After enum value deletion // Data deserializes but status becomes UNSPECIFIED (0) // or causes parsing errors depending on implementation ```","content":"Real-World Example // After enum value deletion // Data deserializes but status becomes UNSPECIFIED (0) // or causes parsing errors depending on implementation ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::22","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - server handles all enum values func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_OR","content":"Real-World Example **Server validation breaks:** ```go // Before - server handles all enum values func validateOrderStatus(status OrderStatus) error { switch status { case OrderStatus_ORDER_STATUS_PENDING, OrderStatus_ORDER_STATUS_CONFIRMED, OrderStatus_ORDER_STATUS_SHIPPED, OrderStatus_ORDER_STATUS_DELIVERED, OrderStatus_ORDER_STATUS_CANCELLED: // ERROR: undefined return nil default: return errors.New(\"invalid order status\") } }"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::real-world-example::23","title":"ENUM_VALUE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Server logic that depends on cancelled status func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR: undefined } ```","content":"Real-World Example // Server logic that depends on cancelled status func canModifyOrder(order *Order) bool { return order.Status != OrderStatus_ORDER_STATUS_CANCELLED // ERROR: undefined } ```"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::24","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate enum values first:**","content":"Migration Strategy **Deprecate enum values first:**"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::25","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using deprecated values** in new code:","content":"Migration Strategy **Stop using deprecated values** in new code:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::26","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update client code** to handle deprecated values gracefully:","content":"Migration Strategy **Update client code** to handle deprecated values gracefully:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::27","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve the values** after sufficient migration period:","content":"Migration Strategy **Reserve the values** after sufficient migration period:"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::migration-strategy::28","title":"ENUM_VALUE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Never reuse enum numbers** - they must remain reserved permanently","content":"Migration Strategy **Never reuse enum numbers** - they must remain reserved permanently"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::proto2-vs-proto3-behavior::29","title":"ENUM_VALUE_NO_DELETE","section":"Proto2 vs Proto3 Behavior","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#proto2-vs-proto3-behavior","headings":["Proto2 vs Proto3 Behavior"],"excerpt":"Proto2 vs Proto3 Behavior ```proto // Proto2: Unknown enum values are preserved in unknown fields // Proto3: Unknown enum values are preserved as-is // Both cases: Don't delete values that might exist in stored data","content":"Proto2 vs Proto3 Behavior ```proto // Proto2: Unknown enum values are preserved in unknown fields // Proto3: Unknown enum values are preserved as-is // Both cases: Don't delete values that might exist in stored data"},{"id":"cli/breaking-changes/rules/enum-value-no-delete::proto2-vs-proto3-behavior::30","title":"ENUM_VALUE_NO_DELETE","section":"Proto2 vs Proto3 Behavior","path":"/docs/guide/cli/breaking-changes/rules/enum-value-no-delete#proto2-vs-proto3-behavior","headings":["Proto2 vs Proto3 Behavior"],"excerpt":"Proto2 vs Proto3 Behavior // Safe approach for both syntax versions: enum MyEnum { MY_ENUM_UNSPECIFIED = 0; MY_ENUM_VALUE_OLD = 1 [deprecated = true]; // Don't delete MY_ENUM_VALUE_NEW = 2; } ```","content":"Proto2 vs Proto3 Behavior // Safe approach for both syntax versions: enum MyEnum { MY_ENUM_UNSPECIFIED = 0; MY_ENUM_VALUE_OLD = 1 [deprecated = true]; // Don't delete MY_ENUM_VALUE_NEW = 2; } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::top::0","title":"ENUM_VALUE_SAME_NAME","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name","headings":[],"excerpt":"This rule checks that enum values maintain the same name for each number. Changing an enum value's name (while keeping the same number) breaks both JSON compatibility and generated code, as clients expect specific consta","content":"This rule checks that enum values maintain the same name for each number. Changing an enum value's name (while keeping the same number) breaks both JSON compatibility and generated code, as clients expect specific constant names."},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::1","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::2","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4; } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::3","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::bad::4","title":"ENUM_VALUE_SAME_NAME","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#bad","headings":["Bad"],"excerpt":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Changed from ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code ","content":"Bad enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code --] Changed from ORDER_STATUS_CONFIRMED ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code --] Changed from ORDER_STATUS_DELIVERED } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::5","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples **Multiple renames breaking clients:**","content":"More Examples **Multiple renames breaking clients:**"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::6","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }","content":"More Examples ```proto // Before enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMIN = 1; USER_ROLE_MODERATOR = 2; USER_ROLE_USER = 3; }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::more-examples::7","title":"ENUM_VALUE_SAME_NAME","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER","content":"More Examples // After - ALL BREAKING CHANGES! enum UserRole { USER_ROLE_UNSPECIFIED = 0; USER_ROLE_ADMINISTRATOR = 1; // BREAKING: ADMIN -> ADMINISTRATOR USER_ROLE_MOD = 2; // BREAKING: MODERATOR -> MOD USER_ROLE_MEMBER = 3; // BREAKING: USER -> MEMBER } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::8","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good **Instead of renaming, add new values and deprecate old ones:** ```proto syntax = \"proto3\";","content":"Good **Instead of renaming, add new values and deprecate old ones:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::9","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2 [deprecated = true]; // [!code focus] ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4 [deprecated = true]; /","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_CONFIRMED = 2 [deprecated = true]; // [!code focus] ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_DELIVERED = 4 [deprecated = true]; // [!code focus] ORDER_STATUS_APPROVED = 5; // [!code focus] // New value instead of renaming ORDER_STATUS_COMPLETED = 6; // [!code focus] // New value instead of renaming } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::10","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good **Or create a new enum version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new enum version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::11","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/enum-value-same-name::good::12","title":"ENUM_VALUE_SAME_NAME","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#good","headings":["Good"],"excerpt":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // Clean names in v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ``","content":"Good enum OrderStatus { ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1; ORDER_STATUS_APPROVED = 2; // [!code focus] // Clean names in v2 ORDER_STATUS_SHIPPED = 3; ORDER_STATUS_COMPLETED = 4; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::impact::13","title":"ENUM_VALUE_SAME_NAME","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Constant names change, breaking client compilation **JSON Compatibility:** JSON serialization uses enum names, breaking parsers **Client Applications:** Code referencing old constant names fail","content":"Impact **Generated Code:** Constant names change, breaking client compilation **JSON Compatibility:** JSON serialization uses enum names, breaking parsers **Client Applications:** Code referencing old constant names fails to compile **Documentation:** API docs become outdated with wrong enum names"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::14","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // handle delivery }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::15","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After rename - compilation fails status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined constant if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined con","content":"Real-World Example // After rename - compilation fails status := myapi.OrderStatus_ORDER_STATUS_CONFIRMED // ERROR: undefined constant if order.Status == myapi.OrderStatus_ORDER_STATUS_DELIVERED { // ERROR: undefined constant // handle delivery } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::16","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **JSON compatibility breaks:** ```json // Before - JSON uses old names { \"status\": \"ORDER_STATUS_CONFIRMED\" }","content":"Real-World Example **JSON compatibility breaks:** ```json // Before - JSON uses old names { \"status\": \"ORDER_STATUS_CONFIRMED\" }"},{"id":"cli/breaking-changes/rules/enum-value-same-name::real-world-example::17","title":"ENUM_VALUE_SAME_NAME","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - parser expects new names { \"status\": \"ORDER_STATUS_APPROVED\" // Old JSON fails to parse } ```","content":"Real-World Example // After - parser expects new names { \"status\": \"ORDER_STATUS_APPROVED\" // Old JSON fails to parse } ```"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::18","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new enum values** instead of renaming:","content":"Migration Strategy **Add new enum values** instead of renaming:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::19","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new values during transition","content":"Migration Strategy **Update server code** to handle both old and new values during transition"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::20","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new enum values","content":"Migration Strategy **Migrate clients** to use new enum values"},{"id":"cli/breaking-changes/rules/enum-value-same-name::migration-strategy::21","title":"ENUM_VALUE_SAME_NAME","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove deprecated values** in next major version:","content":"Migration Strategy **Remove deprecated values** in next major version:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias-exception::22","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias Exception","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias-exception","headings":["Allow Alias Exception"],"excerpt":"Allow Alias Exception With allow_alias = true, you can temporarily have multiple names for the same value:","content":"Allow Alias Exception With allow_alias = true, you can temporarily have multiple names for the same value:"},{"id":"cli/breaking-changes/rules/enum-value-same-name::allow-alias-exception::23","title":"ENUM_VALUE_SAME_NAME","section":"Allow Alias Exception","path":"/docs/guide/cli/breaking-changes/rules/enum-value-same-name#allow-alias-exception","headings":["Allow Alias Exception"],"excerpt":"Allow Alias Exception Note: EasyP currently detects this as breaking even with allow_alias. This may be refined in future versions.","content":"Allow Alias Exception Note: EasyP currently detects this as breaking even with allow_alias. This may be refined in future versions."},{"id":"cli/breaking-changes/rules/field-no-delete::top::0","title":"FIELD_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete","headings":[],"excerpt":"This rule checks that no message fields are deleted. Deleting a field breaks both wire format compatibility and generated code, as existing data may contain the deleted field and client code may reference it.","content":"This rule checks that no message fields are deleted. Deleting a field breaks both wire format compatibility and generated code, as existing data may contain the deleted field and client code may reference it."},{"id":"cli/breaking-changes/rules/field-no-delete::bad::1","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::2","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; string phone = 4; // [!code --] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::3","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::bad::4","title":"FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; // phone field was deleted - BREAKING CHANGE! } ```","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; // phone field was deleted - BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::good::5","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the field:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::good::6","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```","content":"Good message User { string name = 1; string email = 2; int32 age = 3; string phone = 4 [deprecated = true]; // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::good::7","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good **Or reserve the field number after removal:** ```proto syntax = \"proto3\";","content":"Good **Or reserve the field number after removal:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-no-delete::good::8","title":"FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#good","headings":["Good"],"excerpt":"Good message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```","content":"Good message User { reserved 4; // [!code focus] reserved \"phone\"; // [!code focus] string name = 1; string email = 2; int32 age = 3; } ```"},{"id":"cli/breaking-changes/rules/field-no-delete::impact::9","title":"FIELD_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Old messages with the deleted field cannot be properly deserialized **Generated Code:** Field accessors are removed, breaking client compilation **Data Loss:** Existing serialized data loses infor","content":"Impact **Wire Format:** Old messages with the deleted field cannot be properly deserialized **Generated Code:** Field accessors are removed, breaking client compilation **Data Loss:** Existing serialized data loses information **JSON Compatibility:** JSON parsers expect the field to exist"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::10","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::11","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop writing to the field** in your application code","content":"Migration Strategy **Stop writing to the field** in your application code"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::12","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve the field** in next version to prevent accidental reuse:","content":"Migration Strategy **Reserve the field** in next version to prevent accidental reuse:"},{"id":"cli/breaking-changes/rules/field-no-delete::migration-strategy::13","title":"FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Never reuse field numbers** - they must remain reserved permanently","content":"Migration Strategy **Never reuse field numbers** - they must remain reserved permanently"},{"id":"cli/breaking-changes/rules/field-same-cardinality::top::0","title":"FIELD_SAME_CARDINALITY","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality","headings":[],"excerpt":"This rule checks that message fields maintain the same cardinality (optionality). Changing a field's cardinality breaks both wire format compatibility and generated code, as the presence semantics and client code expecta","content":"This rule checks that message fields maintain the same cardinality (optionality). Changing a field's cardinality breaks both wire format compatibility and generated code, as the presence semantics and client code expectations differ between optional and required fields."},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::1","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::2","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; int32 age = 3; }","content":"Bad message User { string name = 1; string email = 2; int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::3","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```","content":"Bad message CreateUserRequest { string name = 1; optional string email = 2; string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::4","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::5","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; optional string email = 2; // [!code --] Changed from required to optional int32 age = 3; }","content":"Bad message User { string name = 1; optional string email = 2; // [!code --] Changed from required to optional int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::bad::6","title":"FIELD_SAME_CARDINALITY","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#bad","headings":["Bad"],"excerpt":"Bad message CreateUserRequest { string name = 1; string email = 2; // [!code --] Changed from optional to required string phone = 3; } ```","content":"Bad message CreateUserRequest { string name = 1; string email = 2; // [!code --] Changed from optional to required string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::7","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples **Proto2 to Proto3 migration issues:**","content":"More Examples **Proto2 to Proto3 migration issues:**"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::8","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before (proto2) syntax = \"proto2\";","content":"More Examples ```proto // Before (proto2) syntax = \"proto2\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::9","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }","content":"More Examples message Order { required string id = 1; optional string notes = 2; repeated string tags = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::10","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";","content":"More Examples // After (proto3) - BREAKING CHANGES! syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::more-examples::11","title":"FIELD_SAME_CARDINALITY","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#more-examples","headings":["More Examples"],"excerpt":"More Examples message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK: repeated unchanged } ```","content":"More Examples message Order { string id = 1; // BREAKING: required -> implicit optional string notes = 2; // BREAKING: explicit optional -> implicit optional repeated string tags = 3; // OK: repeated unchanged } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::12","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good **Instead of changing cardinality, add new field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing cardinality, add new field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::13","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality int32 age = 3; optional string email_optional = 4; // [!code focus] // New field with desired cardi","content":"Good message User { string name = 1; string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality int32 age = 3; optional string email_optional = 4; // [!code focus] // New field with desired cardinality }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::14","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality string phone = 3; string email_required = 4; // [!code focus] // New field wi","content":"Good message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; // [!code focus] // Keep original cardinality string phone = 3; string email_required = 4; // [!code focus] // New field with desired cardinality } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::15","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good **Or create a new message version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::16","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::17","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message User { string name = 1; optional string email = 2; // [!code focus] // Clean cardinality in v2 int32 age = 3; }","content":"Good message User { string name = 1; optional string email = 2; // [!code focus] // Clean cardinality in v2 int32 age = 3; }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::good::18","title":"FIELD_SAME_CARDINALITY","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#good","headings":["Good"],"excerpt":"Good message CreateUserRequest { string name = 1; string email = 2; // [!code focus] // Required in v2 string phone = 3; } ```","content":"Good message CreateUserRequest { string name = 1; string email = 2; // [!code focus] // Required in v2 string phone = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::impact::19","title":"FIELD_SAME_CARDINALITY","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Field presence semantics change, breaking deserialization expectations **Generated Code:** Field accessor methods change (hasField(), clearField()) **Validation:** Required field validation change","content":"Impact **Wire Format:** Field presence semantics change, breaking deserialization expectations **Generated Code:** Field accessor methods change (hasField(), clearField()) **Validation:** Required field validation changes at runtime **Default Values:** Optional vs required fields handle defaults differently"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::20","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks with cardinality changes:** ```go // Before - required field (proto3 implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", // Must be set Age: 30, }","content":"Real-World Example **Client code breaks with cardinality changes:** ```go // Before - required field (proto3 implicit) user := &myapi.User{ Name: \"John\", Email: \"john@example.com\", // Must be set Age: 30, }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::21","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check if email is set (implicit presence) if user.Email != \"\" { // Email is provided }","content":"Real-World Example // Check if email is set (implicit presence) if user.Email != \"\" { // Email is provided }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::22","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - optional field (explicit presence) user := &myapi.User{ Name: \"John\", Age: 30, // Email can be nil/unset }","content":"Real-World Example // After - optional field (explicit presence) user := &myapi.User{ Name: \"John\", Age: 30, // Email can be nil/unset }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::23","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check if email is set (explicit presence) if user.Email != nil && *user.Email != \"\" { // Different API! // Email is provided }","content":"Real-World Example // Check if email is set (explicit presence) if user.Email != nil && *user.Email != \"\" { // Different API! // Email is provided }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::24","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Setting email also changes user.Email = &emailValue // Pointer assignment vs direct ```","content":"Real-World Example // Setting email also changes user.Email = &emailValue // Pointer assignment vs direct ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::25","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - implicit required field func validateUser(user *User) error { if user.Email == \"\" { // Empty string check return errors.New(\"email is required\") } return","content":"Real-World Example **Server validation breaks:** ```go // Before - implicit required field func validateUser(user *User) error { if user.Email == \"\" { // Empty string check return errors.New(\"email is required\") } return nil }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::real-world-example::26","title":"FIELD_SAME_CARDINALITY","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - explicit optional field func validateUser(user *User) error { if user.Email == nil { // Nil pointer check return errors.New(\"email is required\") } if *user.Email == \"\" { // Dereference to ch","content":"Real-World Example // After - explicit optional field func validateUser(user *User) error { if user.Email == nil { // Nil pointer check return errors.New(\"email is required\") } if *user.Email == \"\" { // Dereference to check empty return errors.New(\"email cannot be empty\") } return nil } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::27","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new field** with correct cardinality:","content":"Migration Strategy **Add new field** with correct cardinality:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::28","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Dual-write period** - populate both fields during transition:","content":"Migration Strategy **Dual-write period** - populate both fields during transition:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::29","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update clients** to use new field gradually:","content":"Migration Strategy **Update clients** to use new field gradually:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::migration-strategy::30","title":"FIELD_SAME_CARDINALITY","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old field** in next major version:","content":"Migration Strategy **Remove old field** in next major version:"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-to-proto3-migration::31","title":"FIELD_SAME_CARDINALITY","section":"Proto2 to Proto3 Migration","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-to-proto3-migration","headings":["Proto2 to Proto3 Migration"],"excerpt":"Proto2 to Proto3 Migration ```proto // Instead of direct syntax migration syntax = \"proto3\"; message Order { string id = 1; // BREAKING: was required in proto2 }","content":"Proto2 to Proto3 Migration ```proto // Instead of direct syntax migration syntax = \"proto3\"; message Order { string id = 1; // BREAKING: was required in proto2 }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-to-proto3-migration::32","title":"FIELD_SAME_CARDINALITY","section":"Proto2 to Proto3 Migration","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-to-proto3-migration","headings":["Proto2 to Proto3 Migration"],"excerpt":"Proto2 to Proto3 Migration // Maintain semantics during migration syntax = \"proto3\"; message Order { string id = 1; // Keep as implicit required // Add explicit optional fields only when needed optional string notes = 2;","content":"Proto2 to Proto3 Migration // Maintain semantics during migration syntax = \"proto3\"; message Order { string id = 1; // Keep as implicit required // Add explicit optional fields only when needed optional string notes = 2; } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-optional-fields-required::33","title":"FIELD_SAME_CARDINALITY","section":"Making Optional Fields Required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-optional-fields-required","headings":["Making Optional Fields Required"],"excerpt":"Making Optional Fields Required ```proto // Instead of changing existing field message CreateUserRequest { string name = 1; string email = 2; // BREAKING: was optional }","content":"Making Optional Fields Required ```proto // Instead of changing existing field message CreateUserRequest { string name = 1; string email = 2; // BREAKING: was optional }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-optional-fields-required::34","title":"FIELD_SAME_CARDINALITY","section":"Making Optional Fields Required","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-optional-fields-required","headings":["Making Optional Fields Required"],"excerpt":"Making Optional Fields Required // Add new required field message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; // New required field } ```","content":"Making Optional Fields Required // Add new required field message CreateUserRequest { string name = 1; optional string email = 2 [deprecated = true]; string required_email = 3; // New required field } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-required-fields-optional::35","title":"FIELD_SAME_CARDINALITY","section":"Making Required Fields Optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-required-fields-optional","headings":["Making Required Fields Optional"],"excerpt":"Making Required Fields Optional ```proto // Instead of changing existing field message User { optional string phone = 3; // BREAKING: was required }","content":"Making Required Fields Optional ```proto // Instead of changing existing field message User { optional string phone = 3; // BREAKING: was required }"},{"id":"cli/breaking-changes/rules/field-same-cardinality::making-required-fields-optional::36","title":"FIELD_SAME_CARDINALITY","section":"Making Required Fields Optional","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#making-required-fields-optional","headings":["Making Required Fields Optional"],"excerpt":"Making Required Fields Optional // Add new optional field message User { string phone = 3 [deprecated = true]; // Keep required optional string phone_optional = 4; // New optional field } ```","content":"Making Required Fields Optional // Add new optional field message User { string phone = 3 [deprecated = true]; // Keep required optional string phone_optional = 4; // New optional field } ```"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto3-cardinality::37","title":"FIELD_SAME_CARDINALITY","section":"Proto3 Cardinality","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto3-cardinality","headings":["Proto3 Cardinality"],"excerpt":"Proto3 Cardinality **Implicit optional**: string name = 1; (default in proto3) **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;","content":"Proto3 Cardinality **Implicit optional**: string name = 1; (default in proto3) **Explicit optional**: optional string email = 2; **Repeated**: repeated string tags = 3; **Map**: map metadata = 4;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::proto2-cardinality::38","title":"FIELD_SAME_CARDINALITY","section":"Proto2 Cardinality","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#proto2-cardinality","headings":["Proto2 Cardinality"],"excerpt":"Proto2 Cardinality **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;","content":"Proto2 Cardinality **Required**: required string id = 1; **Optional**: optional string email = 2; **Repeated**: repeated string tags = 3;"},{"id":"cli/breaking-changes/rules/field-same-cardinality::breaking-changes-matrix::39","title":"FIELD_SAME_CARDINALITY","section":"Breaking Changes Matrix","path":"/docs/guide/cli/breaking-changes/rules/field-same-cardinality#breaking-changes-matrix","headings":["Breaking Changes Matrix"],"excerpt":"Breaking Changes Matrix From To Result ------ ---- --------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Single ","content":"Breaking Changes Matrix From To Result ------ ---- --------- Required Optional ❌ BREAKING Optional Required ❌ BREAKING Implicit Explicit ❌ BREAKING Explicit Implicit ❌ BREAKING Single Repeated ❌ BREAKING Repeated Single ❌ BREAKING Field Map ❌ BREAKING Map Field ❌ BREAKING"},{"id":"cli/breaking-changes/rules/field-same-type::top::0","title":"FIELD_SAME_TYPE","path":"/docs/guide/cli/breaking-changes/rules/field-same-type","headings":[],"excerpt":"This rule checks that message fields maintain the same type. Changing a field's type breaks wire format compatibility and generated code, as the binary representation and client code expectations differ between types.","content":"This rule checks that message fields maintain the same type. Changing a field's type breaks wire format compatibility and generated code, as the binary representation and client code expectations differ between types."},{"id":"cli/breaking-changes/rules/field-same-type::bad::1","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::bad::2","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad message Product { string name = 1; int32 price = 2; bool available = 3; } ```","content":"Bad message Product { string name = 1; int32 price = 2; bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::bad::3","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::bad::4","title":"FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#bad","headings":["Bad"],"excerpt":"Bad message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string bool available = 3; } ```","content":"Bad message Product { string name = 1; string price = 2; // [!code --] Changed from int32 to string bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::5","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Incompatible type changes:**","content":"More Examples **Incompatible type changes:**"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::6","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }","content":"More Examples ```proto // Before message Order { string id = 1; int64 timestamp = 2; repeated string tags = 3; OrderStatus status = 4; }"},{"id":"cli/breaking-changes/rules/field-same-type::more-examples::7","title":"FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status","content":"More Examples // After - ALL BREAKING CHANGES! message Order { int32 id = 1; // string -> int32: BREAKING string timestamp = 2; // int64 -> string: BREAKING string tags = 3; // repeated -> singular: BREAKING int32 status = 4; // enum -> int32: BREAKING } ```"},{"id":"cli/breaking-changes/rules/field-same-type::good::8","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good **Instead of changing type, add a new field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing type, add a new field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::good::9","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] bool available = 3; string price_formatted = 4; // [!code focus] // New field for string price } ```","content":"Good message Product { string name = 1; int32 price = 2 [deprecated = true]; // [!code focus] bool available = 3; string price_formatted = 4; // [!code focus] // New field for string price } ```"},{"id":"cli/breaking-changes/rules/field-same-type::good::10","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good **Or create a new message version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/field-same-type::good::11","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/field-same-type::good::12","title":"FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#good","headings":["Good"],"excerpt":"Good message Product { string name = 1; string price = 2; // [!code focus] // Now string in v2 bool available = 3; } ```","content":"Good message Product { string name = 1; string price = 2; // [!code focus] // Now string in v2 bool available = 3; } ```"},{"id":"cli/breaking-changes/rules/field-same-type::impact::13","title":"FIELD_SAME_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** Field types change, breaking client compilation **Runtime Errors:** Type mismatches cause parsing failures **Data ","content":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** Field types change, breaking client compilation **Runtime Errors:** Type mismatches cause parsing failures **Data Corruption:** Incorrect interpretation of binary data"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::14","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new field** with correct type:","content":"Migration Strategy **Add new field** with correct type:"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::15","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Dual-write period** - populate both fields during transition","content":"Migration Strategy **Dual-write period** - populate both fields during transition"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::16","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update clients** to use new field","content":"Migration Strategy **Update clients** to use new field"},{"id":"cli/breaking-changes/rules/field-same-type::migration-strategy::17","title":"FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old field** in next major version:","content":"Migration Strategy **Remove old field** in next major version:"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::18","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) Note: EasyP currently treats ALL type changes as breaking. However, some changes are technically wire-compatible:","content":"Safe Type Changes (Wire Compatible) Note: EasyP currently treats ALL type changes as breaking. However, some changes are technically wire-compatible:"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::19","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) int32 ↔ uint32 (same encoding) int64 ↔ uint64 (same encoding) string → bytes (if UTF-8 valid)","content":"Safe Type Changes (Wire Compatible) int32 ↔ uint32 (same encoding) int64 ↔ uint64 (same encoding) string → bytes (if UTF-8 valid)"},{"id":"cli/breaking-changes/rules/field-same-type::safe-type-changes-wire-compatible::20","title":"FIELD_SAME_TYPE","section":"Safe Type Changes (Wire Compatible)","path":"/docs/guide/cli/breaking-changes/rules/field-same-type#safe-type-changes-wire-compatible","headings":["Safe Type Changes (Wire Compatible)"],"excerpt":"Safe Type Changes (Wire Compatible) These may be supported in future EasyP versions with different strictness levels.","content":"Safe Type Changes (Wire Compatible) These may be supported in future EasyP versions with different strictness levels."},{"id":"cli/breaking-changes/rules/import-no-delete::top::0","title":"IMPORT_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete","headings":[],"excerpt":"This rule checks that no import statements are deleted from proto files. Deleting an import breaks both wire format compatibility and generated code, as the imported types may be referenced in the current file and removi","content":"This rule checks that no import statements are deleted from proto files. Deleting an import breaks both wire format compatibility and generated code, as the imported types may be referenced in the current file and removing the import makes those types unavailable."},{"id":"cli/breaking-changes/rules/import-no-delete::bad::1","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::2","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";","content":"Bad import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; import \"common/user.proto\"; import \"common/address.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::3","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; common.User customer = 4; common.Address shipping_address = 5; } ```","content":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; common.User customer = 4; common.Address shipping_address = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::4","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::5","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/user.proto\"; // [!code --] Deleted import - BREAKING! // import \"common","content":"Bad import \"google/protobuf/timestamp.proto\"; // import \"google/protobuf/duration.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/user.proto\"; // [!code --] Deleted import - BREAKING! // import \"common/address.proto\"; // [!code --] Deleted import - BREAKING!"},{"id":"cli/breaking-changes/rules/import-no-delete::bad::6","title":"IMPORT_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration not available common.User customer = 4; // ERROR: User not available common.Ad","content":"Bad message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3; // ERROR: Duration not available common.User customer = 4; // ERROR: User not available common.Address shipping_address = 5; // ERROR: Address not available } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::7","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Service definition breaks with deleted imports:**","content":"More Examples **Service definition breaks with deleted imports:**"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::8","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";","content":"More Examples ```proto // Before import \"google/api/annotations.proto\"; import \"google/protobuf/empty.proto\"; import \"common/auth.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::9","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); }","content":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); }"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::10","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING: deleted","content":"More Examples // After - BREAKING CHANGES! // import \"google/api/annotations.proto\"; // BREAKING: deleted // import \"google/protobuf/empty.proto\"; // BREAKING: deleted // import \"common/auth.proto\"; // BREAKING: deleted"},{"id":"cli/breaking-changes/rules/import-no-delete::more-examples::11","title":"IMPORT_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations not available get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) return","content":"More Examples service OrderService { rpc GetOrder(GetOrderRequest) returns (Order) { option (google.api.http) = { // ERROR: annotations not available get: \"/v1/orders/{id}\" }; } rpc DeleteOrder(common.AuthRequest) returns (google.protobuf.Empty); // ERROR: types not available } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::good::12","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, keep unused imports:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, keep unused imports:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::good::13","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep even if unused import \"common/user.proto\"; // [!code focus] // Keep even if unused import \"common/address.p","content":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep even if unused import \"common/user.proto\"; // [!code focus] // Keep even if unused import \"common/address.proto\"; // [!code focus] // Keep even if unused"},{"id":"cli/breaking-changes/rules/import-no-delete::good::14","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Removed fields that used Duration, User, Address but kept imports } ```","content":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; // Removed fields that used Duration, User, Address but kept imports } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::good::15","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with equivalent types while keeping imports:** ```proto syntax = \"proto3\";","content":"Good **Or replace with equivalent types while keeping imports:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/import-no-delete::good::16","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep original import import \"common/user.proto\"; // [!code focus] // Keep original import import \"common/address","content":"Good import \"google/protobuf/timestamp.proto\"; import \"google/protobuf/duration.proto\"; // [!code focus] // Keep original import import \"common/user.proto\"; // [!code focus] // Keep original import import \"common/address.proto\"; // [!code focus] // Keep original import import \"common/v2/user.proto\"; // [!code focus] // Add new import"},{"id":"cli/breaking-changes/rules/import-no-delete::good::17","title":"IMPORT_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] // Keep old field common.User customer = 4 [deprecated = tr","content":"Good message Order { string id = 1; google.protobuf.Timestamp created_at = 2; google.protobuf.Duration processing_time = 3 [deprecated = true]; // [!code focus] // Keep old field common.User customer = 4 [deprecated = true]; // [!code focus] // Keep old field common.Address shipping_address = 5 [deprecated = true]; // [!code focus] // Keep old field int32 processing_seconds = 6; // [!code focus] // New field instead of Duration common.v2.UserProfile customer_v2 = 7; // [!code focus] // New field with updated type string shipping_address_text = 8; // [!code focus] // New field with simpler type } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::impact::18","title":"IMPORT_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Imported types become unavailable, breaking compilation **Wire Format:** Messages using imported types cannot be deserialized **Field References:** Any field using imported types becomes invali","content":"Impact **Generated Code:** Imported types become unavailable, breaking compilation **Wire Format:** Messages using imported types cannot be deserialized **Field References:** Any field using imported types becomes invalid **Service Definitions:** RPC methods using imported types break **Options Usage:** Custom options from imports become unavailable"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::19","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", CreatedAt: timestamppb.New(time.Now()), // Uses google.protobuf.Timestamp Customer: &common.User{ // ERR","content":"Real-World Example **Client code breaks:** ```go // Before - this code works order := &myapi.Order{ Id: \"order123\", CreatedAt: timestamppb.New(time.Now()), // Uses google.protobuf.Timestamp Customer: &common.User{ // ERROR after import deletion Id: \"user456\", Name: \"John Doe\", }, ShippingAddress: &common.Address{ // ERROR after import deletion Street: \"123 Main St\", City: \"New York\", }, }"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::20","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: common.User // undefined: common.Address ```","content":"Real-World Example // Generated code compilation fails: // undefined: common.User // undefined: common.Address ```"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::21","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:**","content":"Real-World Example **Server implementation breaks:**"},{"id":"cli/breaking-changes/rules/import-no-delete::real-world-example::22","title":"IMPORT_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Proto compilation breaks:**","content":"Real-World Example **Proto compilation breaks:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::23","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Keep imports even when unused:**","content":"Migration Strategy **Keep imports even when unused:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::24","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new imports alongside old ones:**","content":"Migration Strategy **Add new imports alongside old ones:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::25","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate fields using old imports gradually:**","content":"Migration Strategy **Deprecate fields using old imports gradually:**"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::26","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/import-no-delete::migration-strategy::27","title":"IMPORT_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Only remove imports in major version updates** after all fields are migrated","content":"Migration Strategy **Only remove imports in major version updates** after all fields are migrated"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::28","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies ```proto // Instead of deleting old import immediately // import \"old/user.proto\"; // Don't delete!","content":"Replacing Dependencies ```proto // Instead of deleting old import immediately // import \"old/user.proto\"; // Don't delete!"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::29","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies // Keep both during transition import \"old/user.proto\"; // Keep for backward compatibility import \"new/user.proto\"; // Add new dependency","content":"Replacing Dependencies // Keep both during transition import \"old/user.proto\"; // Keep for backward compatibility import \"new/user.proto\"; // Add new dependency"},{"id":"cli/breaking-changes/rules/import-no-delete::replacing-dependencies::30","title":"IMPORT_NO_DELETE","section":"Replacing Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#replacing-dependencies","headings":["Replacing Dependencies"],"excerpt":"Replacing Dependencies message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```","content":"Replacing Dependencies message Order { old.User customer = 4 [deprecated = true]; new.UserProfile customer_v2 = 5; } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::removing-unused-features::31","title":"IMPORT_NO_DELETE","section":"Removing Unused Features","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#removing-unused-features","headings":["Removing Unused Features"],"excerpt":"Removing Unused Features ```proto // Even if removing features, keep imports import \"feature/analytics.proto\"; // Keep even if analytics removed","content":"Removing Unused Features ```proto // Even if removing features, keep imports import \"feature/analytics.proto\"; // Keep even if analytics removed"},{"id":"cli/breaking-changes/rules/import-no-delete::removing-unused-features::32","title":"IMPORT_NO_DELETE","section":"Removing Unused Features","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#removing-unused-features","headings":["Removing Unused Features"],"excerpt":"Removing Unused Features message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Field removed but import kept } ```","content":"Removing Unused Features message Order { string id = 1; // feature.AnalyticsData analytics = 2; // Field removed but import kept } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf-version-migration::33","title":"IMPORT_NO_DELETE","section":"Protobuf Version Migration","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf-version-migration","headings":["Protobuf Version Migration"],"excerpt":"Protobuf Version Migration ```proto // When migrating protobuf versions, keep old imports import \"google/protobuf/timestamp.proto\"; // Keep standard imports import \"google/protobuf/duration.proto\"; // Even if switching t","content":"Protobuf Version Migration ```proto // When migrating protobuf versions, keep old imports import \"google/protobuf/timestamp.proto\"; // Keep standard imports import \"google/protobuf/duration.proto\"; // Even if switching to alternatives"},{"id":"cli/breaking-changes/rules/import-no-delete::protobuf-version-migration::34","title":"IMPORT_NO_DELETE","section":"Protobuf Version Migration","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#protobuf-version-migration","headings":["Protobuf Version Migration"],"excerpt":"Protobuf Version Migration // Prefer keeping both old and new approaches message Event { google.protobuf.Timestamp timestamp = 1; // Keep old int64 timestamp_millis = 2; // Add alternative } ```","content":"Protobuf Version Migration // Prefer keeping both old and new approaches message Event { google.protobuf.Timestamp timestamp = 1; // Keep old int64 timestamp_millis = 2; // Add alternative } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::35","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies ```proto // Instead of removing complex type imports // import \"complex/config.proto\"; // Don't delete!","content":"Simplifying Dependencies ```proto // Instead of removing complex type imports // import \"complex/config.proto\"; // Don't delete!"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::36","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies // Keep complex import, add simple alternative import \"complex/config.proto\";","content":"Simplifying Dependencies // Keep complex import, add simple alternative import \"complex/config.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::simplifying-dependencies::37","title":"IMPORT_NO_DELETE","section":"Simplifying Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#simplifying-dependencies","headings":["Simplifying Dependencies"],"excerpt":"Simplifying Dependencies message Settings { complex.ConfigData config = 1 [deprecated = true]; // Keep complex option string config_json = 2; // Add simple option } ```","content":"Simplifying Dependencies message Settings { complex.ConfigData config = 1 [deprecated = true]; // Keep complex option string config_json = 2; // Add simple option } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-deletion-vs-field-usage::38","title":"IMPORT_NO_DELETE","section":"Import Deletion vs Field Usage","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-deletion-vs-field-usage","headings":["Import Deletion vs Field Usage"],"excerpt":"Import Deletion vs Field Usage ```proto // Import deletion breaks even if types aren't directly used as fields import \"common/enums.proto\";","content":"Import Deletion vs Field Usage ```proto // Import deletion breaks even if types aren't directly used as fields import \"common/enums.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::import-deletion-vs-field-usage::39","title":"IMPORT_NO_DELETE","section":"Import Deletion vs Field Usage","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-deletion-vs-field-usage","headings":["Import Deletion vs Field Usage"],"excerpt":"Import Deletion vs Field Usage message Order { // Even if no fields directly use common.enums types, // nested messages or oneof fields might use them oneof payment { CreditCardPayment card = 1; // This might internally ","content":"Import Deletion vs Field Usage message Order { // Even if no fields directly use common.enums types, // nested messages or oneof fields might use them oneof payment { CreditCardPayment card = 1; // This might internally use common.enums } } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::transitive-dependencies::40","title":"IMPORT_NO_DELETE","section":"Transitive Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#transitive-dependencies","headings":["Transitive Dependencies"],"excerpt":"Transitive Dependencies ```proto // Deleting an import can break transitive dependencies import \"user.proto\"; // Don't delete even if not directly used","content":"Transitive Dependencies ```proto // Deleting an import can break transitive dependencies import \"user.proto\"; // Don't delete even if not directly used"},{"id":"cli/breaking-changes/rules/import-no-delete::transitive-dependencies::41","title":"IMPORT_NO_DELETE","section":"Transitive Dependencies","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#transitive-dependencies","headings":["Transitive Dependencies"],"excerpt":"Transitive Dependencies message Order { PaymentInfo payment = 1; // PaymentInfo might internally reference user.proto types } ```","content":"Transitive Dependencies message Order { PaymentInfo payment = 1; // PaymentInfo might internally reference user.proto types } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::json-serialization-impact::42","title":"IMPORT_NO_DELETE","section":"JSON Serialization Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#json-serialization-impact","headings":["JSON Serialization Impact"],"excerpt":"JSON Serialization Impact ```proto // Imports affect JSON field names and validation import \"google/protobuf/field_mask.proto\";","content":"JSON Serialization Impact ```proto // Imports affect JSON field names and validation import \"google/protobuf/field_mask.proto\";"},{"id":"cli/breaking-changes/rules/import-no-delete::json-serialization-impact::43","title":"IMPORT_NO_DELETE","section":"JSON Serialization Impact","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#json-serialization-impact","headings":["JSON Serialization Impact"],"excerpt":"JSON Serialization Impact message UpdateRequest { google.protobuf.FieldMask update_mask = 1; // JSON serialization depends on import } ```","content":"JSON Serialization Impact message UpdateRequest { google.protobuf.FieldMask update_mask = 1; // JSON serialization depends on import } ```"},{"id":"cli/breaking-changes/rules/import-no-delete::import-auditing::44","title":"IMPORT_NO_DELETE","section":"Import Auditing","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-auditing","headings":["Import Auditing"],"excerpt":"Import Auditing ```bash Check which imports are actually used $ grep -r \"google.protobuf.Duration\" *.proto $ grep -r \"common.User\" *.proto","content":"Import Auditing ```bash Check which imports are actually used $ grep -r \"google.protobuf.Duration\" *.proto $ grep -r \"common.User\" *.proto"},{"id":"cli/breaking-changes/rules/import-no-delete::import-auditing::45","title":"IMPORT_NO_DELETE","section":"Import Auditing","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#import-auditing","headings":["Import Auditing"],"excerpt":"Import Auditing But still keep imports even if grep shows no usage! ```","content":"Import Auditing But still keep imports even if grep shows no usage! ```"},{"id":"cli/breaking-changes/rules/import-no-delete::different-breaking-change-types::46","title":"IMPORT_NO_DELETE","section":"Different Breaking Change Types","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#different-breaking-change-types","headings":["Different Breaking Change Types"],"excerpt":"Different Breaking Change Types ```proto // Import deletion (this rule) // import \"user.proto\"; // BREAKING: import deleted","content":"Different Breaking Change Types ```proto // Import deletion (this rule) // import \"user.proto\"; // BREAKING: import deleted"},{"id":"cli/breaking-changes/rules/import-no-delete::different-breaking-change-types::47","title":"IMPORT_NO_DELETE","section":"Different Breaking Change Types","path":"/docs/guide/cli/breaking-changes/rules/import-no-delete#different-breaking-change-types","headings":["Different Breaking Change Types"],"excerpt":"Different Breaking Change Types // vs Field deletion (different rule) message Order { string id = 1; // User customer = 2; // BREAKING: field deleted (different from import) } ```","content":"Different Breaking Change Types // vs Field deletion (different rule) message Order { string id = 1; // User customer = 2; // BREAKING: field deleted (different from import) } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::top::0","title":"MESSAGE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete","headings":[],"excerpt":"This rule checks that no messages are deleted from proto files. Deleting a message breaks both wire format compatibility and generated code, as existing data may reference the deleted message and client code depends on t","content":"This rule checks that no messages are deleted from proto files. Deleting a message breaks both wire format compatibility and generated code, as existing data may reference the deleted message and client code depends on the generated types."},{"id":"cli/breaking-changes/rules/message-no-delete::bad::1","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::2","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; Address address = 3; }","content":"Bad message User { string name = 1; string email = 2; Address address = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::3","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]","content":"Bad message Address { // [!code --] string street = 1; // [!code --] string city = 2; // [!code --] string country = 3; // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::4","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; User user = 2; } ```","content":"Bad message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::5","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::6","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address message no longer exists! }","content":"Bad message User { string name = 1; string email = 2; Address address = 3; // ERROR: Address message no longer exists! }"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::7","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad // Address message was deleted - BREAKING CHANGE!","content":"Bad // Address message was deleted - BREAKING CHANGE!"},{"id":"cli/breaking-changes/rules/message-no-delete::bad::8","title":"MESSAGE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; User user = 2; } ```","content":"Bad message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::9","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested message deletion:**","content":"More Examples **Nested message deletion:**"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::10","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }","content":"More Examples ```proto // Before message User { string name = 1; Profile profile = 2; message Profile { // [!code --] string bio = 1; // [!code --] string avatar_url = 2; // [!code --] } // [!code --] }"},{"id":"cli/breaking-changes/rules/message-no-delete::more-examples::11","title":"MESSAGE_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile message deleted // Profile nested message was deleted } ```","content":"More Examples // After - BREAKING CHANGE! message User { string name = 1; Profile profile = 2; // ERROR: Profile message deleted // Profile nested message was deleted } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::good::12","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the message:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the message:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::good::13","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }","content":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::14","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::15","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; User user = 2; } ```","content":"Good message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::good::16","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new message version:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new message version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/message-no-delete::good::17","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Old field AddressV2 address_v2 = 4; // [!code focus] // New field with better structure }","content":"Good message User { string name = 1; string email = 2; Address address = 3 [deprecated = true]; // [!code focus] // Old field AddressV2 address_v2 = 4; // [!code focus] // New field with better structure }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::18","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }","content":"Good message Address { option deprecated = true; // [!code focus] string street = 1; string city = 2; string country = 3; }"},{"id":"cli/breaking-changes/rules/message-no-delete::good::19","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message AddressV2 { // [!code focus] string street_address = 1; // [!code focus] string city = 2; // [!code focus] string state = 3; // [!code focus] string postal_code = 4; // [!code focus] string country = 5; // [","content":"Good message AddressV2 { // [!code focus] string street_address = 1; // [!code focus] string city = 2; // [!code focus] string state = 3; // [!code focus] string postal_code = 4; // [!code focus] string country = 5; // [!code focus] } // [!code focus]"},{"id":"cli/breaking-changes/rules/message-no-delete::good::20","title":"MESSAGE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#good","headings":["Good"],"excerpt":"Good message Order { string id = 1; User user = 2; } ```","content":"Good message Order { string id = 1; User user = 2; } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::impact::21","title":"MESSAGE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with the deleted message cannot be deserialized **Generated Code:** Message classes/structs are removed, breaking client compilation **Field References:** Fields using the deleted me","content":"Impact **Wire Format:** Existing data with the deleted message cannot be deserialized **Generated Code:** Message classes/structs are removed, breaking client compilation **Field References:** Fields using the deleted message type become invalid **Nested Dependencies:** All messages referencing the deleted message break"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::22","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR after deletion Street: \"123 Main St\", City:","content":"Real-World Example **Client code breaks:** ```go // Before - this code works user := &myapi.User{ Name: \"John Doe\", Email: \"john@example.com\", Address: &myapi.Address{ // ERROR after deletion Street: \"123 Main St\", City: \"New York\", Country: \"USA\", }, }"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::23","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.Address ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.Address ```"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::24","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"name\": \"John Doe\", \"email\": \"john@example.com\", \"address\": { \"street\": \"123 Main St\", \"city\": \"New York\", \"country\": ","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"name\": \"John Doe\", \"email\": \"john@example.com\", \"address\": { \"street\": \"123 Main St\", \"city\": \"New York\", \"country\": \"USA\" } }"},{"id":"cli/breaking-changes/rules/message-no-delete::real-world-example::25","title":"MESSAGE_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After Address deletion - deserialization fails // Parser doesn't know how to handle \"address\" field ```","content":"Real-World Example // After Address deletion - deserialization fails // Parser doesn't know how to handle \"address\" field ```"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::26","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the message first:**","content":"Migration Strategy **Deprecate the message first:**"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::27","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Stop using in new fields** and deprecate existing fields that use it:","content":"Migration Strategy **Stop using in new fields** and deprecate existing fields that use it:"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::28","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create replacement** with new structure if needed:","content":"Migration Strategy **Create replacement** with new structure if needed:"},{"id":"cli/breaking-changes/rules/message-no-delete::migration-strategy::29","title":"MESSAGE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/breaking-changes/rules/message-no-delete::refactoring-message-structure::30","title":"MESSAGE_NO_DELETE","section":"Refactoring Message Structure","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#refactoring-message-structure","headings":["Refactoring Message Structure"],"excerpt":"Refactoring Message Structure ```proto // Instead of deleting UserInfo and creating UserProfile message UserInfo { option deprecated = true; // Deprecate old string name = 1; string email = 2; }","content":"Refactoring Message Structure ```proto // Instead of deleting UserInfo and creating UserProfile message UserInfo { option deprecated = true; // Deprecate old string name = 1; string email = 2; }"},{"id":"cli/breaking-changes/rules/message-no-delete::refactoring-message-structure::31","title":"MESSAGE_NO_DELETE","section":"Refactoring Message Structure","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#refactoring-message-structure","headings":["Refactoring Message Structure"],"excerpt":"Refactoring Message Structure message UserProfile { // Create new alongside string full_name = 1; string email_address = 2; string phone = 3; // Better field organization } ```","content":"Refactoring Message Structure message UserProfile { // Create new alongside string full_name = 1; string email_address = 2; string phone = 3; // Better field organization } ```"},{"id":"cli/breaking-changes/rules/message-no-delete::version-migration::32","title":"MESSAGE_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration ```proto // Clean approach - new package version package myapi.v2;","content":"Version Migration ```proto // Clean approach - new package version package myapi.v2;"},{"id":"cli/breaking-changes/rules/message-no-delete::version-migration::33","title":"MESSAGE_NO_DELETE","section":"Version Migration","path":"/docs/guide/cli/breaking-changes/rules/message-no-delete#version-migration","headings":["Version Migration"],"excerpt":"Version Migration message User { // Redesigned message structure // No deprecated Address references } ```","content":"Version Migration message User { // Redesigned message structure // No deprecated Address references } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::top::0","title":"ONEOF_FIELD_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete","headings":[],"excerpt":"This rule checks that no fields are deleted from oneOf groups. Deleting a field from a oneOf breaks both wire format compatibility and generated code, as existing data may use the deleted oneOf option and client code dep","content":"This rule checks that no fields are deleted from oneOf groups. Deleting a field from a oneOf breaks both wire format compatibility and generated code, as existing data may use the deleted oneOf option and client code depends on the generated field types and accessor methods."},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::1","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::2","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; string certificate = 5; } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::3","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```","content":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3; DateRange date_range = 4; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::4","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::5","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Deleted oneOf field - BREAKING! // string certificate = 5; // [!code -","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; // string oauth_token = 4; // [!code --] Deleted oneOf field - BREAKING! // string certificate = 5; // [!code --] Deleted oneOf field - BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::bad::6","title":"ONEOF_FIELD_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#bad","headings":["Bad"],"excerpt":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Deleted oneOf field - BREAKING! // DateRange date_range = 4; // [!code --] Deleted oneOf field - BREAKING","content":"Bad message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; // string category = 3; // [!code --] Deleted oneOf field - BREAKING! // DateRange date_range = 4; // [!code --] Deleted oneOf field - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::7","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested message oneOf field deletion:**","content":"More Examples **Nested message oneOf field deletion:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::8","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; CryptoPayment crypto = 4; // [!code --] Gift","content":"More Examples ```proto // Before message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; CryptoPayment crypto = 4; // [!code --] GiftCardPayment gift_card = 5; // [!code --] } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::more-examples::9","title":"ONEOF_FIELD_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto = 4; // BR","content":"More Examples // After - BREAKING CHANGES! message PaymentRequest { string order_id = 1; oneof payment_method { CreditCardPayment credit_card = 2; BankTransferPayment bank_transfer = 3; // CryptoPayment crypto = 4; // BREAKING: deleted // GiftCardPayment gift_card = 5; // BREAKING: deleted } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::10","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the oneOf fields:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the oneOf fields:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::11","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] string certificate = 5 [deprecated = true]; // [!","content":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] string certificate = 5 [deprecated = true]; // [!code focus] } }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::12","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3 [deprecated = true]; // [!code focus] DateRange date_range = 4 [deprecated = true]; // [!code focus] } } ```","content":"Good message SearchQuery { oneof filter { string text = 1; int32 user_id = 2; string category = 3 [deprecated = true]; // [!code focus] DateRange date_range = 4 [deprecated = true]; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::13","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good **Or add new oneOf fields while keeping old ones:** ```proto syntax = \"proto3\";","content":"Good **Or add new oneOf fields while keeping old ones:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::good::14","title":"ONEOF_FIELD_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Keep old field string certificate = 5 [depreca","content":"Good message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4 [deprecated = true]; // [!code focus] // Keep old field string certificate = 5 [deprecated = true]; // [!code focus] // Keep old field OAuthCredentials oauth_v2 = 6; // [!code focus] // New structured approach CertificateCredentials cert_v2 = 7; // [!code focus] // New structured approach } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact::15","title":"ONEOF_FIELD_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing data with deleted oneOf fields cannot be deserialized properly **Generated Code:** OneOf field accessor methods are removed, breaking client compilation **Type Safety:** Generated oneOf w","content":"Impact **Wire Format:** Existing data with deleted oneOf fields cannot be deserialized properly **Generated Code:** OneOf field accessor methods are removed, breaking client compilation **Type Safety:** Generated oneOf wrapper types lose options, breaking switch statements **Business Logic:** Client code handling specific oneOf cases breaks"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::16","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::17","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set OAuth token (oneOf field) loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR after field deletion }","content":"Real-World Example // Set OAuth token (oneOf field) loginReq.Credentials = &myapi.LoginRequest_OauthToken{ OauthToken: \"token123\", // ERROR after field deletion }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::18","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch on oneOf field types switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: ","content":"Real-World Example // Switch on oneOf field types switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: return authenticatePassword(cred.Password) case *myapi.LoginRequest_OauthToken: // ERROR: undefined type after deletion return authenticateOAuth(cred.OauthToken) case *myapi.LoginRequest_Certificate: // ERROR: undefined type after deletion return authenticateCert(cred.Certificate) default: return errors.New(\"unsupported credential type\") }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::19","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_OauthToken // undefined: myapi.LoginRequest_Certificate ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::20","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server handling breaks:**","content":"Real-World Example **Server handling breaks:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::21","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"username\": \"user123\", \"oauth_token\": \"abc123xyz\" }","content":"Real-World Example **Existing data becomes unreadable:** ```json // Serialized data before deletion { \"username\": \"user123\", \"oauth_token\": \"abc123xyz\" }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::real-world-example::22","title":"ONEOF_FIELD_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf field deletion // Data deserializes but oauth_token is lost or causes parsing errors // User authentication fails due to missing credential data ```","content":"Real-World Example // After oneOf field deletion // Data deserializes but oauth_token is lost or causes parsing errors // User authentication fails due to missing credential data ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::23","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate oneOf fields first:**","content":"Migration Strategy **Deprecate oneOf fields first:**"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::24","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new fields** if replacement is needed:","content":"Migration Strategy **Add new fields** if replacement is needed:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::25","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::26","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new fields:","content":"Migration Strategy **Migrate clients** to use new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::migration-strategy::27","title":"ONEOF_FIELD_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Reserve field numbers** after removal in next major version:","content":"Migration Strategy **Reserve field numbers** after removal in next major version:"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::removing-unsupported-authentication-methods::28","title":"ONEOF_FIELD_NO_DELETE","section":"Removing Unsupported Authentication Methods","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#removing-unsupported-authentication-methods","headings":["Removing Unsupported Authentication Methods"],"excerpt":"Removing Unsupported Authentication Methods","content":"Removing Unsupported Authentication Methods"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::oneof-field-deletion-vs-other-deletions::29","title":"ONEOF_FIELD_NO_DELETE","section":"OneOf Field Deletion vs Other Deletions","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#oneof-field-deletion-vs-other-deletions","headings":["OneOf Field Deletion vs Other Deletions"],"excerpt":"OneOf Field Deletion vs Other Deletions","content":"OneOf Field Deletion vs Other Deletions"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::different-from-regular-field-deletion::30","title":"ONEOF_FIELD_NO_DELETE","section":"Different from Regular Field Deletion","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#different-from-regular-field-deletion","headings":["Different from Regular Field Deletion"],"excerpt":"Different from Regular Field Deletion ```proto // Regular field deletion (also breaking) message User { string name = 1; // string email = 2; // BREAKING: regular field deletion }","content":"Different from Regular Field Deletion ```proto // Regular field deletion (also breaking) message User { string name = 1; // string email = 2; // BREAKING: regular field deletion }"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::different-from-regular-field-deletion::31","title":"ONEOF_FIELD_NO_DELETE","section":"Different from Regular Field Deletion","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#different-from-regular-field-deletion","headings":["Different from Regular Field Deletion"],"excerpt":"Different from Regular Field Deletion // OneOf field deletion (breaks oneOf semantics) message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: oneOf field deletion } } ```","content":"Different from Regular Field Deletion // OneOf field deletion (breaks oneOf semantics) message User { oneof contact { string email = 1; // string phone = 2; // BREAKING: oneOf field deletion } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact-on-generated-code::32","title":"ONEOF_FIELD_NO_DELETE","section":"Impact on Generated Code","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact-on-generated-code","headings":["Impact on Generated Code"],"excerpt":"Impact on Generated Code ```go // Regular field - simple accessor removed // user.GetEmail() // Method removed","content":"Impact on Generated Code ```go // Regular field - simple accessor removed // user.GetEmail() // Method removed"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::impact-on-generated-code::33","title":"ONEOF_FIELD_NO_DELETE","section":"Impact on Generated Code","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#impact-on-generated-code","headings":["Impact on Generated Code"],"excerpt":"Impact on Generated Code // OneOf field - wrapper type removed // *LoginRequest_OauthToken // Entire type removed // switch statement cases break completely ```","content":"Impact on Generated Code // OneOf field - wrapper type removed // *LoginRequest_OauthToken // Entire type removed // switch statement cases break completely ```"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::wire-format-considerations::34","title":"ONEOF_FIELD_NO_DELETE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations ```proto // OneOf fields share the same \"choice\" semantics // Removing a choice breaks clients that made that choice","content":"Wire Format Considerations ```proto // OneOf fields share the same \"choice\" semantics // Removing a choice breaks clients that made that choice"},{"id":"cli/breaking-changes/rules/oneof-field-no-delete::wire-format-considerations::35","title":"ONEOF_FIELD_NO_DELETE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-no-delete#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations message Request { oneof data { string text = 1; // Choice A bytes binary = 2; // Choice B - if removed, clients using B break JsonData json = 3; // Choice C } } ```","content":"Wire Format Considerations message Request { oneof data { string text = 1; // Choice A bytes binary = 2; // Choice B - if removed, clients using B break JsonData json = 3; // Choice C } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::top::0","title":"ONEOF_FIELD_SAME_TYPE","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type","headings":[],"excerpt":"This rule checks that oneOf field types cannot be changed. Changing the type of a field within a oneOf breaks both wire format compatibility and generated code, as existing data contains the old type and client code expe","content":"This rule checks that oneOf field types cannot be changed. Changing the type of a field within a oneOf breaks both wire format compatibility and generated code, as existing data contains the old type and client code expects specific field types in oneOf wrapper structures."},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::1","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::2","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }","content":"Bad message SearchRequest { string query = 1; oneof filter { string category = 2; int32 user_id = 3; bool is_premium = 4; DateRange date_range = 5; } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::3","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```","content":"Bad message NotificationSettings { oneof delivery { string email = 1; int64 phone_number = 2; WebhookConfig webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::4","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::5","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Changed from string to int32 - BREAKING! string user_id = 3; // [!code --] Changed from int32 to string - BREAKING! string is","content":"Bad message SearchRequest { string query = 1; oneof filter { int32 category = 2; // [!code --] Changed from string to int32 - BREAKING! string user_id = 3; // [!code --] Changed from int32 to string - BREAKING! string is_premium = 4; // [!code --] Changed from bool to string - BREAKING! string date_range = 5; // [!code --] Changed from DateRange to string - BREAKING! } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::bad::6","title":"ONEOF_FIELD_SAME_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#bad","headings":["Bad"],"excerpt":"Bad message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Changed from string to EmailConfig - BREAKING! string phone_number = 2; // [!code --] Changed from int64 to string - BREAKING! stri","content":"Bad message NotificationSettings { oneof delivery { EmailConfig email = 1; // [!code --] Changed from string to EmailConfig - BREAKING! string phone_number = 2; // [!code --] Changed from int64 to string - BREAKING! string webhook = 3; // [!code --] Changed from WebhookConfig to string - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::7","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Complex type changes:**","content":"More Examples **Complex type changes:**"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::8","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWalletInfo crypto = 4; } }","content":"More Examples ```proto // Before message PaymentRequest { oneof payment_info { CreditCardInfo credit_card = 1; BankAccountInfo bank_account = 2; string paypal_email = 3; CryptoWalletInfo crypto = 4; } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::more-examples::9","title":"ONEOF_FIELD_SAME_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - ALL BREAKING CHANGES! message PaymentRequest { oneof payment_info { string credit_card = 1; // BREAKING: CreditCardInfo -> string PayPalInfo bank_account = 2; // BREAKING: BankAccountInfo -> PayP","content":"More Examples // After - ALL BREAKING CHANGES! message PaymentRequest { oneof payment_info { string credit_card = 1; // BREAKING: CreditCardInfo -> string PayPalInfo bank_account = 2; // BREAKING: BankAccountInfo -> PayPalInfo PayPalInfo paypal_email = 3; // BREAKING: string -> PayPalInfo string crypto = 4; // BREAKING: CryptoWalletInfo -> string } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::10","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good **Instead of changing type, add new oneOf field:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing type, add new oneOf field:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::11","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // [!code focus] // Keep original type int32 user_id = 3 [deprecated = true]; // [!code focus] // Keep original type ","content":"Good message SearchRequest { string query = 1; oneof filter { string category = 2 [deprecated = true]; // [!code focus] // Keep original type int32 user_id = 3 [deprecated = true]; // [!code focus] // Keep original type bool is_premium = 4 [deprecated = true]; // [!code focus] // Keep original type DateRange date_range = 5 [deprecated = true]; // [!code focus] // Keep original type int32 category_id = 6; // [!code focus] // New field with desired type string user_identifier = 7; // [!code focus] // New field with desired type string premium_status = 8; // [!code focus] // New field with desired type string date_filter = 9; // [!code focus] // New field with desired type } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::12","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good **Or create a new oneOf group:** ```proto syntax = \"proto3\";","content":"Good **Or create a new oneOf group:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::good::13","title":"ONEOF_FIELD_SAME_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#good","headings":["Good"],"excerpt":"Good message SearchRequest { string query = 1; oneof filter { option deprecated = true; // [!code focus] // Deprecate old oneOf string category = 2 [deprecated = true]; // [!code focus] int32 user_id = 3 [deprecated = tr","content":"Good message SearchRequest { string query = 1; oneof filter { option deprecated = true; // [!code focus] // Deprecate old oneOf string category = 2 [deprecated = true]; // [!code focus] int32 user_id = 3 [deprecated = true]; // [!code focus] bool is_premium = 4 [deprecated = true]; // [!code focus] DateRange date_range = 5 [deprecated = true]; // [!code focus] } oneof filter_v2 { // [!code focus] // New oneOf with correct types int32 category_id = 6; // [!code focus] string user_identifier = 7; // [!code focus] PremiumFilter premium_filter = 8; // [!code focus] TimeFilter time_filter = 9; // [!code focus] } // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::impact::14","title":"ONEOF_FIELD_SAME_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** OneOf wrapper types change, breaking client compilation **Type Safety:** Switch statements on oneOf types break wi","content":"Impact **Wire Format:** Binary data cannot be deserialized correctly between versions **Generated Code:** OneOf wrapper types change, breaking client compilation **Type Safety:** Switch statements on oneOf types break with compilation errors **Runtime Errors:** Type mismatches cause parsing failures for existing data"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::15","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }","content":"Real-World Example **Client code breaks:** ```go // Before - this code works searchReq := &myapi.SearchRequest{ Query: \"golang jobs\", }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::16","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set filter using oneOf (original types) searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // string type }","content":"Real-World Example // Set filter using oneOf (original types) searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // string type }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::17","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Handle filter types switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // string parameter case *myapi.SearchRequest_UserId: retu","content":"Real-World Example // Handle filter types switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // string parameter case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // int32 parameter default: return errors.New(\"unsupported filter\") }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::18","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After type change - compilation fails searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR: expects int32, not string }","content":"Real-World Example // After type change - compilation fails searchReq.Filter = &myapi.SearchRequest_Category{ Category: \"engineering\", // ERROR: expects int32, not string }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::19","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Switch statement breaks switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR: Category is now int32 case *myapi.SearchRequ","content":"Real-World Example // Switch statement breaks switch filter := searchReq.Filter.(type) { case *myapi.SearchRequest_Category: return searchByCategory(filter.Category) // ERROR: Category is now int32 case *myapi.SearchRequest_UserId: return searchByUserId(filter.UserId) // ERROR: UserId is now string } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::20","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server expects original types func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchR","content":"Real-World Example **Server implementation breaks:** ```go // Before - server expects original types func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryName := filter.Category // string return searchDatabase(\"category\", categoryName), nil case *SearchRequest_UserId: userId := filter.UserId // int32 return searchDatabase(\"user_id\", strconv.Itoa(int(userId))), nil default: return nil, errors.New(\"no filter specified\") } }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::21","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After type change - runtime errors func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryId := filter.Catego","content":"Real-World Example // After type change - runtime errors func handleSearchFilter(req *SearchRequest) (*SearchResult, error) { switch filter := req.Filter.(type) { case *SearchRequest_Category: categoryId := filter.Category // now int32, but code expects string return searchDatabase(\"category\", categoryId), nil // ERROR: type mismatch case *SearchRequest_UserId: userIdStr := filter.UserId // now string, but conversion logic expects int32 userId, _ := strconv.Atoi(userIdStr) // Works but semantics changed return searchDatabase(\"user_id\", strconv.Itoa(userId)), nil } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::22","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Existing data corruption:** ```json // Serialized data before type change { \"query\": \"golang jobs\", \"category\": \"engineering\" }","content":"Real-World Example **Existing data corruption:** ```json // Serialized data before type change { \"query\": \"golang jobs\", \"category\": \"engineering\" }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::real-world-example::23","title":"ONEOF_FIELD_SAME_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After changing category from string to int32 // Data cannot be deserialized - \"engineering\" is not a valid int32 // Results in parsing errors or data loss ```","content":"Real-World Example // After changing category from string to int32 // Data cannot be deserialized - \"engineering\" is not a valid int32 // Results in parsing errors or data loss ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::24","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new oneOf fields** with correct types:","content":"Migration Strategy **Add new oneOf fields** with correct types:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::25","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both old and new fields:","content":"Migration Strategy **Update server code** to handle both old and new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::26","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new fields:","content":"Migration Strategy **Migrate clients** to use new fields:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::27","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Provide migration utilities** for data conversion:","content":"Migration Strategy **Provide migration utilities** for data conversion:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::migration-strategy::28","title":"ONEOF_FIELD_SAME_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old fields** in next major version:","content":"Migration Strategy **Remove old fields** in next major version:"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::type-change-compatibility-matrix::29","title":"ONEOF_FIELD_SAME_TYPE","section":"Type Change Compatibility Matrix","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#type-change-compatibility-matrix","headings":["Type Change Compatibility Matrix"],"excerpt":"Type Change Compatibility Matrix","content":"Type Change Compatibility Matrix"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::never-compatible-always-breaking::30","title":"ONEOF_FIELD_SAME_TYPE","section":"Never Compatible (Always Breaking)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#never-compatible-always-breaking","headings":["Never Compatible (Always Breaking)"],"excerpt":"Never Compatible (Always Breaking) From Type To Type Result ----------- --------- --------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING","content":"Never Compatible (Always Breaking) From Type To Type Result ----------- --------- --------- string int32/int64 ❌ BREAKING int32 string ❌ BREAKING bool string ❌ BREAKING message string ❌ BREAKING string message ❌ BREAKING enum int32 ❌ BREAKING"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::31","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact ```go // String to int32 change breaks wrapper types // Before: type SearchRequest_Category struct { Category string }","content":"Generated Code Impact ```go // String to int32 change breaks wrapper types // Before: type SearchRequest_Category struct { Category string }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::32","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // After: type SearchRequest_Category struct { Category int32 // Different type - compilation fails }","content":"Generated Code Impact // After: type SearchRequest_Category struct { Category int32 // Different type - compilation fails }"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::generated-code-impact::33","title":"ONEOF_FIELD_SAME_TYPE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // All client code using SearchRequest_Category breaks ```","content":"Generated Code Impact // All client code using SearchRequest_Category breaks ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::wire-format-considerations::34","title":"ONEOF_FIELD_SAME_TYPE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations ```proto // OneOf fields in wire format are identified by field number // Type changes break deserialization even if field number stays same","content":"Wire Format Considerations ```proto // OneOf fields in wire format are identified by field number // Type changes break deserialization even if field number stays same"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::wire-format-considerations::35","title":"ONEOF_FIELD_SAME_TYPE","section":"Wire Format Considerations","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#wire-format-considerations","headings":["Wire Format Considerations"],"excerpt":"Wire Format Considerations message Request { oneof data { string text = 1; // Wire tag: 1, type: string // int32 text = 1; // Same wire tag, different type - BREAKING! } } ```","content":"Wire Format Considerations message Request { oneof data { string text = 1; // Wire tag: 1, type: string // int32 text = 1; // Same wire tag, different type - BREAKING! } } ```"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::type-safe-validation-before-change::36","title":"ONEOF_FIELD_SAME_TYPE","section":"Type-Safe Validation (Before Change)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#type-safe-validation-before-change","headings":["Type-Safe Validation (Before Change)"],"excerpt":"Type-Safe Validation (Before Change)","content":"Type-Safe Validation (Before Change)"},{"id":"cli/breaking-changes/rules/oneof-field-same-type::broken-validation-after-type-change::37","title":"ONEOF_FIELD_SAME_TYPE","section":"Broken Validation (After Type Change)","path":"/docs/guide/cli/breaking-changes/rules/oneof-field-same-type#broken-validation-after-type-change","headings":["Broken Validation (After Type Change)"],"excerpt":"Broken Validation (After Type Change)","content":"Broken Validation (After Type Change)"},{"id":"cli/breaking-changes/rules/oneof-no-delete::top::0","title":"ONEOF_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete","headings":[],"excerpt":"This rule checks that no oneOf fields are deleted from messages. Deleting a oneOf breaks both wire format compatibility and generated code, as existing data may use the oneOf structure and client code depends on the gene","content":"This rule checks that no oneOf fields are deleted from messages. Deleting a oneOf breaks both wire format compatibility and generated code, as existing data may use the oneOf structure and client code depends on the generated oneOf types and accessor methods."},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::1","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::2","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }","content":"Bad message LoginRequest { string username = 1; oneof credentials { string password = 2; string api_key = 3; string oauth_token = 4; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::3","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] } // [!code --","content":"Bad message PaymentMethod { // [!code --] oneof method { // [!code --] CreditCard credit_card = 1; // [!code --] BankAccount bank_account = 2; // [!code --] PayPal paypal = 3; // [!code --] } // [!code --] } // [!code --]"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::4","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::5","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::6","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message LoginRequest { string username = 1; // credentials oneof was deleted - BREAKING CHANGE! string password = 2; // Now regular fields string api_key = 3; // Lost exclusive semantics string oauth_token = 4; }","content":"Bad message LoginRequest { string username = 1; // credentials oneof was deleted - BREAKING CHANGE! string password = 2; // Now regular fields string api_key = 3; // Lost exclusive semantics string oauth_token = 4; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::7","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message PaymentMethod { // method oneof was deleted - BREAKING CHANGE! CreditCard credit_card = 1; // Now all can be set simultaneously BankAccount bank_account = 2; PayPal paypal = 3; }","content":"Bad message PaymentMethod { // method oneof was deleted - BREAKING CHANGE! CreditCard credit_card = 1; // Now all can be set simultaneously BankAccount bank_account = 2; PayPal paypal = 3; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::bad::8","title":"ONEOF_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#bad","headings":["Bad"],"excerpt":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```","content":"Bad message Order { string id = 1; PaymentMethod payment = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::9","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples **Nested oneOf deletion:**","content":"More Examples **Nested oneOf deletion:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::10","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2; // [!code --] string slack_id = 3; // [","content":"More Examples ```proto // Before message UserProfile { string name = 1; message ContactInfo { oneof contact_method { // [!code --] string email = 1; // [!code --] string phone = 2; // [!code --] string slack_id = 3; // [!code --] } // [!code --] } ContactInfo contact = 2; }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::more-examples::11","title":"ONEOF_NO_DELETE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof was deleted string email = 1; // No longer mutually exclusive string phone = 2; // Can set al","content":"More Examples // After - BREAKING CHANGE! message UserProfile { string name = 1; message ContactInfo { // contact_method oneof was deleted string email = 1; // No longer mutually exclusive string phone = 2; // Can set all fields now string slack_id = 3; } ContactInfo contact = 2; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::12","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the oneOf:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the oneOf:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::13","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code ","content":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code focus] string oauth_token = 4 [deprecated = true]; // [!code focus] } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::14","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; // [!code focus] P","content":"Good message PaymentMethod { oneof method { option deprecated = true; // [!code focus] CreditCard credit_card = 1 [deprecated = true]; // [!code focus] BankAccount bank_account = 2 [deprecated = true]; // [!code focus] PayPal paypal = 3 [deprecated = true]; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::15","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good **Or replace with new structure:** ```proto syntax = \"proto3\";","content":"Good **Or replace with new structure:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/oneof-no-delete::good::16","title":"ONEOF_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#good","headings":["Good"],"excerpt":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Old oneOf string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true","content":"Good message LoginRequest { string username = 1; oneof credentials { option deprecated = true; // [!code focus] // Old oneOf string password = 2 [deprecated = true]; // [!code focus] string api_key = 3 [deprecated = true]; // [!code focus] string oauth_token = 4 [deprecated = true]; // [!code focus] } oneof auth_method { // [!code focus] // New oneOf with better design PasswordAuth password_auth = 5; // [!code focus] ApiKeyAuth api_auth = 6; // [!code focus] OAuthAuth oauth_auth = 7; // [!code focus] } // [!code focus] } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::impact::17","title":"ONEOF_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** OneOf semantics are lost - fields are no longer mutually exclusive **Generated Code:** OneOf accessor methods are removed, breaking client compilation **Business Logic:** Mutual exclusivity constr","content":"Impact **Wire Format:** OneOf semantics are lost - fields are no longer mutually exclusive **Generated Code:** OneOf accessor methods are removed, breaking client compilation **Business Logic:** Mutual exclusivity constraints are violated **Validation:** Client code expecting only one field to be set may break"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::18","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - oneOf provides mutual exclusivity loginReq := &myapi.LoginRequest{ Username: \"user123\", }","content":"Real-World Example **Client code breaks:** ```go // Before - oneOf provides mutual exclusivity loginReq := &myapi.LoginRequest{ Username: \"user123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::19","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Set one of the credential options (oneOf semantics) loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }","content":"Real-World Example // Set one of the credential options (oneOf semantics) loginReq.Credentials = &myapi.LoginRequest_Password{ Password: \"secret123\", }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::20","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Check which credential type is set switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR after oneOf deletion return authenticatePassword(cred.Password) case *myap","content":"Real-World Example // Check which credential type is set switch cred := loginReq.Credentials.(type) { case *myapi.LoginRequest_Password: // ERROR after oneOf deletion return authenticatePassword(cred.Password) case *myapi.LoginRequest_ApiKey: // ERROR after oneOf deletion return authenticateApiKey(cred.ApiKey) default: return errors.New(\"no credentials provided\") }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::21","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```","content":"Real-World Example // Generated code compilation fails: // undefined: myapi.LoginRequest_Password // undefined field: loginReq.Credentials ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::22","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server validation breaks:** ```go // Before - server validates oneOf semantics func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required","content":"Real-World Example **Server validation breaks:** ```go // Before - server validates oneOf semantics func validateLoginRequest(req *LoginRequest) error { if req.Credentials == nil { return errors.New(\"credentials required\") } // OneOf ensures only one credential type is set switch req.Credentials.(type) { case *LoginRequest_Password: return validatePassword(req.GetPassword()) case *LoginRequest_ApiKey: return validateApiKey(req.GetApiKey()) case *LoginRequest_OauthToken: return validateOAuthToken(req.GetOauthToken()) default: return errors.New(\"unknown credential type\") } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::23","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf deletion - validation logic breaks func validateLoginRequest(req *LoginRequest) error { // No more oneOf - multiple fields can be set! credCount := 0 if req.Password != \"\" { credCount++ ","content":"Real-World Example // After oneOf deletion - validation logic breaks func validateLoginRequest(req *LoginRequest) error { // No more oneOf - multiple fields can be set! credCount := 0 if req.Password != \"\" { credCount++ } if req.ApiKey != \"\" { credCount++ } if req.OauthToken != \"\" { credCount++ } if credCount == 0 { return errors.New(\"no credentials provided\") } if credCount > 1 { return errors.New(\"multiple credentials provided\") // Manual check needed! } // Lost type safety - need manual checks if req.Password != \"\" { return validatePassword(req.Password) } // ... more manual validation } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::24","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Business logic problems:** ```go // Before - oneOf guarantees mutual exclusivity payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, } // Impossi","content":"Real-World Example **Business logic problems:** ```go // Before - oneOf guarantees mutual exclusivity payment := &PaymentMethod{ Method: &PaymentMethod_CreditCard{ CreditCard: &CreditCard{Number: \"1234\"}, }, } // Impossible to set multiple payment methods simultaneously"},{"id":"cli/breaking-changes/rules/oneof-no-delete::real-world-example::25","title":"ONEOF_NO_DELETE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After oneOf deletion - business logic can break payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Both set! Logic breaks! } ```","content":"Real-World Example // After oneOf deletion - business logic can break payment := &PaymentMethod{ CreditCard: &CreditCard{Number: \"1234\"}, BankAccount: &BankAccount{Number: \"5678\"}, // Both set! Logic breaks! } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::26","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate the oneOf and all its fields:**","content":"Migration Strategy **Deprecate the oneOf and all its fields:**"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::27","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Create new structure** if needed:","content":"Migration Strategy **Create new structure** if needed:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::28","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Update server code** to handle both during transition:","content":"Migration Strategy **Update server code** to handle both during transition:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::29","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new structure:","content":"Migration Strategy **Migrate clients** to use new structure:"},{"id":"cli/breaking-changes/rules/oneof-no-delete::migration-strategy::30","title":"ONEOF_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old oneOf** in next major version","content":"Migration Strategy **Remove old oneOf** in next major version"},{"id":"cli/breaking-changes/rules/oneof-no-delete::replacing-oneof-with-regular-fields::31","title":"ONEOF_NO_DELETE","section":"Replacing OneOf with Regular Fields","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#replacing-oneof-with-regular-fields","headings":["Replacing OneOf with Regular Fields"],"excerpt":"Replacing OneOf with Regular Fields ```proto // Instead of removing oneOf structure entirely message SearchRequest { // Don't delete oneOf - breaks mutual exclusivity string text_query = 1; // BREAKING: was in oneOf int3","content":"Replacing OneOf with Regular Fields ```proto // Instead of removing oneOf structure entirely message SearchRequest { // Don't delete oneOf - breaks mutual exclusivity string text_query = 1; // BREAKING: was in oneOf int32 user_id = 2; // BREAKING: was in oneOf string category = 3; // BREAKING: was in oneOf }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::replacing-oneof-with-regular-fields::32","title":"ONEOF_NO_DELETE","section":"Replacing OneOf with Regular Fields","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#replacing-oneof-with-regular-fields","headings":["Replacing OneOf with Regular Fields"],"excerpt":"Replacing OneOf with Regular Fields // Keep oneOf, add new fields if needed message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]","content":"Replacing OneOf with Regular Fields // Keep oneOf, add new fields if needed message SearchRequest { oneof query { option deprecated = true; string text_query = 1 [deprecated = true]; int32 user_id = 2 [deprecated = true]; string category = 3 [deprecated = true]; } // Add new non-exclusive fields if that's the intent string search_text = 4; repeated string filters = 5; } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::simplifying-message-structure::33","title":"ONEOF_NO_DELETE","section":"Simplifying Message Structure","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#simplifying-message-structure","headings":["Simplifying Message Structure"],"excerpt":"Simplifying Message Structure ```proto // Instead of flattening oneOf structure message NotificationSettings { // Don't delete oneOf - loses type safety string email = 1; // BREAKING: was in oneOf string phone = 2; // BR","content":"Simplifying Message Structure ```proto // Instead of flattening oneOf structure message NotificationSettings { // Don't delete oneOf - loses type safety string email = 1; // BREAKING: was in oneOf string phone = 2; // BREAKING: was in oneOf string webhook_url = 3; // BREAKING: was in oneOf }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::simplifying-message-structure::34","title":"ONEOF_NO_DELETE","section":"Simplifying Message Structure","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#simplifying-message-structure","headings":["Simplifying Message Structure"],"excerpt":"Simplifying Message Structure // Keep oneOf for type safety message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```","content":"Simplifying Message Structure // Keep oneOf for type safety message NotificationSettings { oneof delivery_method { EmailNotification email = 1; SmsNotification phone = 2; WebhookNotification webhook = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::35","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration ```proto // When migrating from proto2 to proto3 // Don't lose oneOf semantics during migration","content":"Proto Syntax Migration ```proto // When migrating from proto2 to proto3 // Don't lose oneOf semantics during migration"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::36","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }","content":"Proto Syntax Migration // proto2 message Request { optional string name = 1; oneof data { string text = 2; int32 number = 3; } }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::proto-syntax-migration::37","title":"ONEOF_NO_DELETE","section":"Proto Syntax Migration","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#proto-syntax-migration","headings":["Proto Syntax Migration"],"excerpt":"Proto Syntax Migration // proto3 - keep oneOf structure message Request { string name = 1; oneof data { // Don't delete this! string text = 2; int32 number = 3; } } ```","content":"Proto Syntax Migration // proto3 - keep oneOf structure message Request { string name = 1; oneof data { // Don't delete this! string text = 2; int32 number = 3; } } ```"},{"id":"cli/breaking-changes/rules/oneof-no-delete::what-oneof-provides::38","title":"ONEOF_NO_DELETE","section":"What OneOf Provides","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#what-oneof-provides","headings":["What OneOf Provides"],"excerpt":"What OneOf Provides **Mutual Exclusivity**: Only one field can be set at a time **Type Safety**: Generated code enforces single choice **Clear Intent**: API design expresses \"choose one\" semantics **Efficient Wire Format","content":"What OneOf Provides **Mutual Exclusivity**: Only one field can be set at a time **Type Safety**: Generated code enforces single choice **Clear Intent**: API design expresses \"choose one\" semantics **Efficient Wire Format**: Only selected field is serialized"},{"id":"cli/breaking-changes/rules/oneof-no-delete::whats-lost-when-deleted::39","title":"ONEOF_NO_DELETE","section":"What's Lost When Deleted","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#whats-lost-when-deleted","headings":["What's Lost When Deleted"],"excerpt":"What's Lost When Deleted **Business Logic**: No enforcement of mutual exclusivity **Generated Code**: No oneOf wrapper types or methods **Validation**: Manual checks needed for exclusivity **API Clarity**: Intent of \"cho","content":"What's Lost When Deleted **Business Logic**: No enforcement of mutual exclusivity **Generated Code**: No oneOf wrapper types or methods **Validation**: Manual checks needed for exclusivity **API Clarity**: Intent of \"choose one\" is lost"},{"id":"cli/breaking-changes/rules/oneof-no-delete::generated-code-impact::40","title":"ONEOF_NO_DELETE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact ```go // With oneOf - type safe type LoginRequest struct { Username string // Types that are assignable to Credentials: // *LoginRequest_Password // *LoginRequest_ApiKey Credentials isLoginRequest_C","content":"Generated Code Impact ```go // With oneOf - type safe type LoginRequest struct { Username string // Types that are assignable to Credentials: // *LoginRequest_Password // *LoginRequest_ApiKey Credentials isLoginRequest_Credentials }"},{"id":"cli/breaking-changes/rules/oneof-no-delete::generated-code-impact::41","title":"ONEOF_NO_DELETE","section":"Generated Code Impact","path":"/docs/guide/cli/breaking-changes/rules/oneof-no-delete#generated-code-impact","headings":["Generated Code Impact"],"excerpt":"Generated Code Impact // Without oneOf - no type safety type LoginRequest struct { Username string Password string // All can be set simultaneously ApiKey string // No mutual exclusivity OauthToken string } ```","content":"Generated Code Impact // Without oneOf - no type safety type LoginRequest struct { Username string Password string // All can be set simultaneously ApiKey string // No mutual exclusivity OauthToken string } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::top::0","title":"RPC_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete","headings":[],"excerpt":"This rule checks that no RPC methods are deleted from services. Deleting an RPC method breaks both generated code and client applications that call the method.","content":"This rule checks that no RPC methods are deleted from services. Deleting an RPC method breaks both generated code and client applications that call the method."},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::1","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::2","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); // [!code -","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); // [!code --] } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::3","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::bad::4","title":"RPC_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC was deleted - BREAKING CHANGE! } ```","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // DeleteUser RPC was deleted - BREAKING CHANGE! } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::good::5","title":"RPC_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-no-delete::good::6","title":"RPC_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) { option de","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) { option deprecated = true; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/rpc-no-delete::impact::7","title":"RPC_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** RPC method stubs are removed, breaking client compilation **Client Applications:** Existing calls to the RPC fail to compile **Runtime:** gRPC clients lose method definition","content":"Impact **Generated Code:** RPC method stubs are removed, breaking client compilation **Client Applications:** Existing calls to the RPC fail to compile **Runtime:** gRPC clients lose method definition"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::8","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::9","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Return error from implementation** indicating method is no longer supported","content":"Migration Strategy **Return error from implementation** indicating method is no longer supported"},{"id":"cli/breaking-changes/rules/rpc-no-delete::migration-strategy::10","title":"RPC_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove in next major version** after clients have migrated","content":"Migration Strategy **Remove in next major version** after clients have migrated"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::top::0","title":"RPC_SAME_REQUEST_TYPE","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type","headings":[],"excerpt":"This rule checks that RPC methods maintain the same request message type. Changing an RPC's request type breaks both wire format compatibility and generated code, as clients expect specific message structures when callin","content":"This rule checks that RPC methods maintain the same request message type. Changing an RPC's request type breaks both wire format compatibility and generated code, as clients expect specific message structures when calling the method."},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::1","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::2","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::3","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserRequest { string user_id = 1; }","content":"Bad message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::4","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```","content":"Bad message UpdateUserRequest { string user_id = 1; string name = 2; string email = 3; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::5","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::6","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Changed request type rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Changed request type }","content":"Bad service UserService { rpc GetUser(GetUserRequestV2) returns (GetUserResponse); // [!code --] Changed request type rpc UpdateUser(UserUpdateRequest) returns (UpdateUserResponse); // [!code --] Changed request type }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::7","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserRequestV2 { // [!code --] Different message type string id = 1; bool include_profile = 2; }","content":"Bad message GetUserRequestV2 { // [!code --] Different message type string id = 1; bool include_profile = 2; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::bad::8","title":"RPC_SAME_REQUEST_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#bad","headings":["Bad"],"excerpt":"Bad message UserUpdateRequest { // [!code --] Different message type string id = 1; UserProfile profile = 2; } ```","content":"Bad message UserUpdateRequest { // [!code --] Different message type string id = 1; UserProfile profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::9","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Cross-package type changes:**","content":"More Examples **Cross-package type changes:**"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::10","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"common/user.proto\";","content":"More Examples ```proto // Before import \"common/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::11","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::12","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! import \"v2/user.proto\";","content":"More Examples // After - BREAKING CHANGE! import \"v2/user.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::more-examples::13","title":"RPC_SAME_REQUEST_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Different package } ```","content":"More Examples service UserService { rpc CreateUser(v2.CreateUserRequest) returns (CreateUserResponse); // Different package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::14","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good **Instead of changing request type, version the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing request type, version the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::15","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // New RPC metho","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequestV2) returns (GetUserResponse); // [!code focus] // New RPC method rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UserUpdateRequest) returns (UpdateUserResponse); // [!code focus] // New RPC method }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::16","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good // Keep old messages for backward compatibility message GetUserRequest { string user_id = 1; }","content":"Good // Keep old messages for backward compatibility message GetUserRequest { string user_id = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::17","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good // Add new messages for enhanced functionality message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Good // Add new messages for enhanced functionality message GetUserRequestV2 { // [!code focus] string id = 1; // [!code focus] bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::18","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good **Or create a new service version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new service version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::19","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::20","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::good::21","title":"RPC_SAME_REQUEST_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#good","headings":["Good"],"excerpt":"Good message GetUserRequest { // [!code focus] string id = 1; // [!code focus] // Improved field names bool include_profile = 2; // [!code focus] } // [!code focus] ```","content":"Good message GetUserRequest { // [!code focus] string id = 1; // [!code focus] // Improved field names bool include_profile = 2; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::impact::22","title":"RPC_SAME_REQUEST_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Existing client requests cannot be deserialized by new server **Generated Code:** Client stubs expect different request message types, breaking compilation **gRPC Calls:** Method signatures change","content":"Impact **Wire Format:** Existing client requests cannot be deserialized by new server **Generated Code:** Client stubs expect different request message types, breaking compilation **gRPC Calls:** Method signatures change in generated client code **Runtime Errors:** Type mismatches cause RPC call failures"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::23","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })","content":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::24","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After request type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: type not found UserId: \"user123\", // ERROR:","content":"Real-World Example // After request type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ // ERROR: type not found UserId: \"user123\", // ERROR: field not found })"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::25","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Must use new type: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", // Different field name IncludeProfile: true, // New required field }) ```","content":"Real-World Example // Must use new type: resp, err := client.GetUser(ctx, &myapi.GetUserRequestV2{ Id: \"user123\", // Different field name IncludeProfile: true, // New required field }) ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::26","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server expects GetUserRequest func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // ","content":"Real-World Example **Server implementation breaks:** ```go // Before - server expects GetUserRequest func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { userID := req.UserId // This field exists // ... implementation }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::real-world-example::27","title":"RPC_SAME_REQUEST_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - server must handle GetUserRequestV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id // Different field name includeProfile :","content":"Real-World Example // After - server must handle GetUserRequestV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequestV2) (*GetUserResponse, error) { userID := req.Id // Different field name includeProfile := req.IncludeProfile // New field to handle // ... implementation must change } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::28","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new RPC method** with improved request type:","content":"Migration Strategy **Add new RPC method** with improved request type:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::29","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Implement both methods** on server during transition:","content":"Migration Strategy **Implement both methods** on server during transition:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::30","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new RPC method:","content":"Migration Strategy **Migrate clients** to use new RPC method:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::migration-strategy::31","title":"RPC_SAME_REQUEST_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old RPC** in next major version:","content":"Migration Strategy **Remove old RPC** in next major version:"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::adding-required-fields::32","title":"RPC_SAME_REQUEST_TYPE","section":"Adding Required Fields","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#adding-required-fields","headings":["Adding Required Fields"],"excerpt":"Adding Required Fields ```proto // Instead of modifying existing request message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING: new required field }","content":"Adding Required Fields ```proto // Instead of modifying existing request message GetUserRequest { string user_id = 1; bool include_deleted = 2; // BREAKING: new required field }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::adding-required-fields::33","title":"RPC_SAME_REQUEST_TYPE","section":"Adding Required Fields","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#adding-required-fields","headings":["Adding Required Fields"],"excerpt":"Adding Required Fields // Add new RPC method message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; // Safe in new method } ```","content":"Adding Required Fields // Add new RPC method message GetUserRequestV2 { string user_id = 1; bool include_deleted = 2; // Safe in new method } ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::restructuring-request-data::34","title":"RPC_SAME_REQUEST_TYPE","section":"Restructuring Request Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#restructuring-request-data","headings":["Restructuring Request Data"],"excerpt":"Restructuring Request Data ```proto // Instead of changing field structure message UpdateUserRequest { UserProfile profile = 1; // BREAKING: was individual fields }","content":"Restructuring Request Data ```proto // Instead of changing field structure message UpdateUserRequest { UserProfile profile = 1; // BREAKING: was individual fields }"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::restructuring-request-data::35","title":"RPC_SAME_REQUEST_TYPE","section":"Restructuring Request Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#restructuring-request-data","headings":["Restructuring Request Data"],"excerpt":"Restructuring Request Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```","content":"Restructuring Request Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (...) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequestV2) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::package-migrations::36","title":"RPC_SAME_REQUEST_TYPE","section":"Package Migrations","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#package-migrations","headings":["Package Migrations"],"excerpt":"Package Migrations ```proto // Instead of changing import packages import \"v2/messages.proto\"; // BREAKING: different package","content":"Package Migrations ```proto // Instead of changing import packages import \"v2/messages.proto\"; // BREAKING: different package"},{"id":"cli/breaking-changes/rules/rpc-same-request-type::package-migrations::37","title":"RPC_SAME_REQUEST_TYPE","section":"Package Migrations","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-request-type#package-migrations","headings":["Package Migrations"],"excerpt":"Package Migrations // Keep old RPC, add new one rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```","content":"Package Migrations // Keep old RPC, add new one rpc OldMethod(v1.Request) returns (...) { option deprecated = true; } rpc NewMethod(v2.Request) returns (...); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::top::0","title":"RPC_SAME_RESPONSE_TYPE","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type","headings":[],"excerpt":"This rule checks that RPC methods maintain the same response message type. Changing an RPC's response type breaks both wire format compatibility and generated code, as clients expect specific message structures when rece","content":"This rule checks that RPC methods maintain the same response message type. Changing an RPC's response type breaks both wire format compatibility and generated code, as clients expect specific message structures when receiving responses from the method."},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::1","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::2","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::3","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Bad message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::4","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message UpdateUserResponse { bool success = 1; string message = 2; } ```","content":"Bad message UpdateUserResponse { bool success = 1; string message = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::5","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::6","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Changed response type rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Changed response type }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponseV2); // [!code --] Changed response type rpc UpdateUser(UpdateUserRequest) returns (UserUpdateResponse); // [!code --] Changed response type }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::7","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message GetUserResponseV2 { // [!code --] Different message type string id = 1; UserProfile profile = 2; repeated string permissions = 3; }","content":"Bad message GetUserResponseV2 { // [!code --] Different message type string id = 1; UserProfile profile = 2; repeated string permissions = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::bad::8","title":"RPC_SAME_RESPONSE_TYPE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#bad","headings":["Bad"],"excerpt":"Bad message UserUpdateResponse { // [!code --] Different message type UpdateResult result = 1; UserProfile updated_profile = 2; } ```","content":"Bad message UserUpdateResponse { // [!code --] Different message type UpdateResult result = 1; UserProfile updated_profile = 2; } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::9","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples **Cross-package type changes:**","content":"More Examples **Cross-package type changes:**"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::10","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples ```proto // Before import \"common/responses.proto\";","content":"More Examples ```proto // Before import \"common/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::11","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::12","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples // After - BREAKING CHANGE! import \"v2/responses.proto\";","content":"More Examples // After - BREAKING CHANGE! import \"v2/responses.proto\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::more-examples::13","title":"RPC_SAME_RESPONSE_TYPE","section":"More Examples","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#more-examples","headings":["More Examples"],"excerpt":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Different package } ```","content":"More Examples service UserService { rpc CreateUser(CreateUserRequest) returns (v2.CreateUserResponse); // Different package } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::14","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good **Instead of changing response type, version the RPC:** ```proto syntax = \"proto3\";","content":"Good **Instead of changing response type, version the RPC:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::15","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // New RPC metho","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; // [!code focus] } rpc GetUserV2(GetUserRequest) returns (GetUserResponseV2); // [!code focus] // New RPC method rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; // [!code focus] } rpc UpdateUserV2(UpdateUserRequest) returns (UserUpdateResponse); // [!code focus] // New RPC method }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::16","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good // Keep old messages for backward compatibility message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }","content":"Good // Keep old messages for backward compatibility message GetUserResponse { string user_id = 1; string name = 2; string email = 3; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::17","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good // Add new messages for enhanced functionality message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus]","content":"Good // Add new messages for enhanced functionality message GetUserResponseV2 { // [!code focus] string id = 1; // [!code focus] UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::18","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good **Or create a new service version:** ```proto syntax = \"proto3\";","content":"Good **Or create a new service version:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::19","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good package myapi.v2; // [!code focus] // New package version","content":"Good package myapi.v2; // [!code focus] // New package version"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::20","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // [!code focus] // Clean interface in v2 rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); // [!code focus] }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::good::21","title":"RPC_SAME_RESPONSE_TYPE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#good","headings":["Good"],"excerpt":"Good message GetUserResponse { // [!code focus] string id = 1; // [!code focus] // Improved field names UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```","content":"Good message GetUserResponse { // [!code focus] string id = 1; // [!code focus] // Improved field names UserProfile profile = 2; // [!code focus] repeated string permissions = 3; // [!code focus] } // [!code focus] ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::impact::22","title":"RPC_SAME_RESPONSE_TYPE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#impact","headings":["Impact"],"excerpt":"Impact **Wire Format:** Server responses cannot be deserialized by existing clients **Generated Code:** Client stubs expect different response message types, breaking compilation **gRPC Calls:** Method signatures change ","content":"Impact **Wire Format:** Server responses cannot be deserialized by existing clients **Generated Code:** Client stubs expect different response message types, breaking compilation **gRPC Calls:** Method signatures change in generated client code **Runtime Errors:** Type mismatches cause RPC response handling failures"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::23","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return","content":"Real-World Example **Client code breaks:** ```go // Before - this code works client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::24","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Access response fields userID := resp.UserId // This field exists name := resp.Name // This field exists","content":"Real-World Example // Access response fields userID := resp.UserId // This field exists name := resp.Name // This field exists"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::25","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After response type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }","content":"Real-World Example // After response type change - compilation fails client := myapi.NewUserServiceClient(conn) resp, err := client.GetUser(ctx, &myapi.GetUserRequest{ UserId: \"user123\", }) if err != nil { return err }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::26","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Access response fields - COMPILATION ERRORS userID := resp.UserId // ERROR: field not found name := resp.Name // ERROR: field not found","content":"Real-World Example // Access response fields - COMPILATION ERRORS userID := resp.UserId // ERROR: field not found name := resp.Name // ERROR: field not found"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::27","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // Must use new fields: userID := resp.Id // Different field name profile := resp.Profile // New structure permissions := resp.Permissions // New field ```","content":"Real-World Example // Must use new fields: userID := resp.Id // Different field name profile := resp.Profile // New structure permissions := resp.Permissions // New field ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::28","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example **Server implementation breaks:** ```go // Before - server returns GetUserResponse func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse","content":"Real-World Example **Server implementation breaks:** ```go // Before - server returns GetUserResponse func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponse, error) { return &GetUserResponse{ UserId: \"user123\", Name: \"John Doe\", Email: \"john@example.com\", }, nil }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::real-world-example::29","title":"RPC_SAME_RESPONSE_TYPE","section":"Real-World Example","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#real-world-example","headings":["Real-World Example"],"excerpt":"Real-World Example // After - server must return GetUserResponseV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", // Different f","content":"Real-World Example // After - server must return GetUserResponseV2 func (s *server) GetUser(ctx context.Context, req *GetUserRequest) (*GetUserResponseV2, error) { return &GetUserResponseV2{ Id: \"user123\", // Different field name Profile: &UserProfile{ // New structure required Name: \"John Doe\", Email: \"john@example.com\", }, Permissions: []string{\"read\"}, // New field to populate }, nil } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::30","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Add new RPC method** with improved response type:","content":"Migration Strategy **Add new RPC method** with improved response type:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::31","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Implement both methods** on server during transition:","content":"Migration Strategy **Implement both methods** on server during transition:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::32","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Migrate clients** to use new RPC method:","content":"Migration Strategy **Migrate clients** to use new RPC method:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::migration-strategy::33","title":"RPC_SAME_RESPONSE_TYPE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove old RPC** in next major version:","content":"Migration Strategy **Remove old RPC** in next major version:"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::adding-fields-to-response::34","title":"RPC_SAME_RESPONSE_TYPE","section":"Adding Fields to Response","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#adding-fields-to-response","headings":["Adding Fields to Response"],"excerpt":"Adding Fields to Response ```proto // Instead of modifying existing response message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING: new required field }","content":"Adding Fields to Response ```proto // Instead of modifying existing response message GetUserResponse { string user_id = 1; string name = 2; UserProfile profile = 3; // BREAKING: new required field }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::adding-fields-to-response::35","title":"RPC_SAME_RESPONSE_TYPE","section":"Adding Fields to Response","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#adding-fields-to-response","headings":["Adding Fields to Response"],"excerpt":"Adding Fields to Response // Add new RPC method message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; // Safe in new method } ```","content":"Adding Fields to Response // Add new RPC method message GetUserResponseV2 { string user_id = 1; string name = 2; UserProfile profile = 3; // Safe in new method } ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::restructuring-response-data::36","title":"RPC_SAME_RESPONSE_TYPE","section":"Restructuring Response Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#restructuring-response-data","headings":["Restructuring Response Data"],"excerpt":"Restructuring Response Data ```proto // Instead of changing field structure message UpdateUserResponse { UserDetails details = 1; // BREAKING: was individual fields }","content":"Restructuring Response Data ```proto // Instead of changing field structure message UpdateUserResponse { UserDetails details = 1; // BREAKING: was individual fields }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::restructuring-response-data::37","title":"RPC_SAME_RESPONSE_TYPE","section":"Restructuring Response Data","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#restructuring-response-data","headings":["Restructuring Response Data"],"excerpt":"Restructuring Response Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```","content":"Restructuring Response Data // Version the RPC rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse) { option deprecated = true; } rpc UpdateUserV2(UpdateUserRequest) returns (UpdateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::error-handling-changes::38","title":"RPC_SAME_RESPONSE_TYPE","section":"Error Handling Changes","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#error-handling-changes","headings":["Error Handling Changes"],"excerpt":"Error Handling Changes ```proto // Instead of changing error structure message CreateUserResponse { ErrorDetails error = 1; // BREAKING: different error format }","content":"Error Handling Changes ```proto // Instead of changing error structure message CreateUserResponse { ErrorDetails error = 1; // BREAKING: different error format }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::error-handling-changes::39","title":"RPC_SAME_RESPONSE_TYPE","section":"Error Handling Changes","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#error-handling-changes","headings":["Error Handling Changes"],"excerpt":"Error Handling Changes // Keep old RPC, add new one rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```","content":"Error Handling Changes // Keep old RPC, add new one rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) { option deprecated = true; } rpc CreateUserV2(CreateUserRequest) returns (CreateUserResponseV2); ```"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::response-format-migration::40","title":"RPC_SAME_RESPONSE_TYPE","section":"Response Format Migration","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#response-format-migration","headings":["Response Format Migration"],"excerpt":"Response Format Migration ```proto // Instead of changing from simple to complex response message GetUserResponse { // BREAKING: changed from simple fields to nested structure UserData data = 1; }","content":"Response Format Migration ```proto // Instead of changing from simple to complex response message GetUserResponse { // BREAKING: changed from simple fields to nested structure UserData data = 1; }"},{"id":"cli/breaking-changes/rules/rpc-same-response-type::response-format-migration::41","title":"RPC_SAME_RESPONSE_TYPE","section":"Response Format Migration","path":"/docs/guide/cli/breaking-changes/rules/rpc-same-response-type#response-format-migration","headings":["Response Format Migration"],"excerpt":"Response Format Migration // Provide both formats during transition rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse","content":"Response Format Migration // Provide both formats during transition rpc GetUser(GetUserRequest) returns (GetUserResponse) { option deprecated = true; } rpc GetUserDetailed(GetUserRequest) returns (GetUserDetailedResponse); ```"},{"id":"cli/breaking-changes/rules/service-no-delete::top::0","title":"SERVICE_NO_DELETE","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete","headings":[],"excerpt":"This rule checks that no services are deleted from proto files. Deleting a service breaks both generated code and client applications that depend on the service.","content":"This rule checks that no services are deleted from proto files. Deleting a service breaks both generated code and client applications that depend on the service."},{"id":"cli/breaking-changes/rules/service-no-delete::bad::1","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad **Before:** ```proto syntax = \"proto3\";","content":"Bad **Before:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::2","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::3","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```","content":"Bad service OrderService { // [!code --] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse); // [!code --] } // [!code --] ```"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::4","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad **After:** ```proto syntax = \"proto3\";","content":"Bad **After:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::5","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Bad service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::bad::6","title":"SERVICE_NO_DELETE","section":"Bad","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#bad","headings":["Bad"],"excerpt":"Bad // OrderService was deleted - BREAKING CHANGE! ```","content":"Bad // OrderService was deleted - BREAKING CHANGE! ```"},{"id":"cli/breaking-changes/rules/service-no-delete::good::7","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good **Instead of deleting, deprecate the service:** ```proto syntax = \"proto3\";","content":"Good **Instead of deleting, deprecate the service:** ```proto syntax = \"proto3\";"},{"id":"cli/breaking-changes/rules/service-no-delete::good::8","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }","content":"Good service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); }"},{"id":"cli/breaking-changes/rules/service-no-delete::good::9","title":"SERVICE_NO_DELETE","section":"Good","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#good","headings":["Good"],"excerpt":"Good service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```","content":"Good service OrderService { option deprecated = true; // [!code focus] rpc GetOrder(GetOrderRequest) returns (GetOrderResponse) { option deprecated = true; // [!code focus] } } ```"},{"id":"cli/breaking-changes/rules/service-no-delete::impact::10","title":"SERVICE_NO_DELETE","section":"Impact","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#impact","headings":["Impact"],"excerpt":"Impact **Generated Code:** Service classes/interfaces are removed, breaking client compilation **Client Applications:** Existing client code fails to compile **Runtime:** gRPC clients lose service definition","content":"Impact **Generated Code:** Service classes/interfaces are removed, breaking client compilation **Client Applications:** Existing client code fails to compile **Runtime:** gRPC clients lose service definition"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::11","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Deprecate first:**","content":"Migration Strategy **Deprecate first:**"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::12","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Notify clients** about deprecation timeline","content":"Migration Strategy **Notify clients** about deprecation timeline"},{"id":"cli/breaking-changes/rules/service-no-delete::migration-strategy::13","title":"SERVICE_NO_DELETE","section":"Migration Strategy","path":"/docs/guide/cli/breaking-changes/rules/service-no-delete#migration-strategy","headings":["Migration Strategy"],"excerpt":"Migration Strategy **Remove after migration period** in a new major version","content":"Migration Strategy **Remove after migration period** in a new major version"},{"id":"cli/configuration/configuration::top::0","title":"EasyP Configuration Reference","path":"/docs/guide/cli/configuration/configuration","headings":[],"excerpt":"EasyP can be configured through CLI flags, environment variables, and configuration files. This guide covers all configuration options available in EasyP.","content":"EasyP can be configured through CLI flags, environment variables, and configuration files. This guide covers all configuration options available in EasyP."},{"id":"cli/configuration/configuration::global-flags::1","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Available for all commands:","content":"Global Flags Available for all commands:"},{"id":"cli/configuration/configuration::global-flags::2","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --cfg -c EASYP_CFG Configuration file path easyp.yaml --config EASYP_CFG Alias for --cfg easyp.yaml --debug -d ","content":"Global Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --cfg -c EASYP_CFG Configuration file path easyp.yaml --config EASYP_CFG Alias for --cfg easyp.yaml --debug -d EASYP_DEBUG Enable debug mode false --format -f EASYP_FORMAT Output format for commands that support multiple formats (text/json) command-specific default"},{"id":"cli/configuration/configuration::global-flags::3","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags **Examples:** ```bash Use custom config file easyp --cfg production.easyp.yaml lint","content":"Global Flags **Examples:** ```bash Use custom config file easyp --cfg production.easyp.yaml lint"},{"id":"cli/configuration/configuration::global-flags::4","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Enable debug logging easyp --debug lint","content":"Global Flags Enable debug logging easyp --debug lint"},{"id":"cli/configuration/configuration::global-flags::5","title":"EasyP Configuration Reference","section":"Global Flags","path":"/docs/guide/cli/configuration/configuration#global-flags","headings":["Global Flags"],"excerpt":"Global Flags Short form easyp -c custom.yaml -d lint ```","content":"Global Flags Short form easyp -c custom.yaml -d lint ```"},{"id":"cli/configuration/configuration::command-specific-flags::6","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Lint command:**","content":"Command-Specific Flags **Lint command:**"},{"id":"cli/configuration/configuration::command-specific-flags::7","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Base directory for file search Current working directory","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p Directory path to lint . --root -r Base directory for file search Current working directory --format -f EASYP_FORMAT Uses global format flag (text/json) Inherits global default"},{"id":"cli/configuration/configuration::command-specific-flags::8","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Lint specific directory easyp lint --path proto/","content":"Command-Specific Flags **Examples:** ```bash Lint specific directory easyp lint --path proto/"},{"id":"cli/configuration/configuration::command-specific-flags::9","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Lint from subdirectory with proper import resolution easyp lint --root src/IPC/Contracts --path .","content":"Command-Specific Flags Lint from subdirectory with proper import resolution easyp lint --root src/IPC/Contracts --path ."},{"id":"cli/configuration/configuration::command-specific-flags::10","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags JSON output format easyp --format json lint # global flag","content":"Command-Specific Flags JSON output format easyp --format json lint # global flag"},{"id":"cli/configuration/configuration::command-specific-flags::11","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Combined flags easyp -f json lint -p proto/ ```","content":"Command-Specific Flags Combined flags easyp -f json lint -p proto/ ```"},{"id":"cli/configuration/configuration::command-specific-flags::12","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Generate command:**","content":"Command-Specific Flags **Generate command:**"},{"id":"cli/configuration/configuration::command-specific-flags::13","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Directory path with proto files to generate . --root -r Base direc","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --path -p EASYP_ROOT_GENERATE_PATH Directory path with proto files to generate . --root -r Base directory for file search Current working directory"},{"id":"cli/configuration/configuration::command-specific-flags::14","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Generate from specific path easyp generate --path api/","content":"Command-Specific Flags **Examples:** ```bash Generate from specific path easyp generate --path api/"},{"id":"cli/configuration/configuration::command-specific-flags::15","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Generate from subdirectory with proper import resolution easyp generate --root src/IPC/Contracts --path .","content":"Command-Specific Flags Generate from subdirectory with proper import resolution easyp generate --root src/IPC/Contracts --path ."},{"id":"cli/configuration/configuration::command-specific-flags::16","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Using environment variable EASYP_ROOT_GENERATE_PATH=proto/ easyp generate ```","content":"Command-Specific Flags Using environment variable EASYP_ROOT_GENERATE_PATH=proto/ easyp generate ```"},{"id":"cli/configuration/configuration::command-specific-flags::17","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Breaking command:**","content":"Command-Specific Flags **Breaking command:**"},{"id":"cli/configuration/configuration::command-specific-flags::18","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --against Git ref to compare against master --path -p Directory path to check . --format -f EASYP_FOR","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --against Git ref to compare against master --path -p Directory path to check . --format -f EASYP_FORMAT Uses global format flag (text/json) Inherits global default"},{"id":"cli/configuration/configuration::command-specific-flags::19","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Check against main branch easyp breaking --against main","content":"Command-Specific Flags **Examples:** ```bash Check against main branch easyp breaking --against main"},{"id":"cli/configuration/configuration::command-specific-flags::20","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Check specific directory against develop branch easyp breaking --against develop --path proto/","content":"Command-Specific Flags Check specific directory against develop branch easyp breaking --against develop --path proto/"},{"id":"cli/configuration/configuration::command-specific-flags::21","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags JSON output easyp --format json breaking --against main # global flag ```","content":"Command-Specific Flags JSON output easyp --format json breaking --against main # global flag ```"},{"id":"cli/configuration/configuration::command-specific-flags::22","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Init command:**","content":"Command-Specific Flags **Init command:**"},{"id":"cli/configuration/configuration::command-specific-flags::23","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --dir -d EASYP_INIT_DIR Directory to initialize .","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --dir -d EASYP_INIT_DIR Directory to initialize ."},{"id":"cli/configuration/configuration::command-specific-flags::24","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Initialize current directory easyp init","content":"Command-Specific Flags **Examples:** ```bash Initialize current directory easyp init"},{"id":"cli/configuration/configuration::command-specific-flags::25","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Initialize specific directory easyp init --dir proto-project/ ```","content":"Command-Specific Flags Initialize specific directory easyp init --dir proto-project/ ```"},{"id":"cli/configuration/configuration::command-specific-flags::26","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags easyp init is interactive: If buf.yml/buf.yaml exists in the target directory root, it asks whether to migrate from Buf. If easyp.yaml already exists, it asks for overwrite confirmation.","content":"Command-Specific Flags easyp init is interactive: If buf.yml/buf.yaml exists in the target directory root, it asks whether to migrate from Buf. If easyp.yaml already exists, it asks for overwrite confirmation."},{"id":"cli/configuration/configuration::command-specific-flags::27","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Validate-config command:**","content":"Command-Specific Flags **Validate-config command:**"},{"id":"cli/configuration/configuration::command-specific-flags::28","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Configuration file path easyp.yaml --format (global) -f EASYP_FORMAT Output for","content":"Command-Specific Flags Flag Short Environment Description Default ------ ------- ------------- ------------- --------- --config -c EASYP_CFG Configuration file path easyp.yaml --format (global) -f EASYP_FORMAT Output format for commands that support multiple formats (json or text) command-specific (json for validate-config)"},{"id":"cli/configuration/configuration::command-specific-flags::29","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Examples:** ```bash Validate default config with JSON output (exit 0 when no errors) easyp validate-config","content":"Command-Specific Flags **Examples:** ```bash Validate default config with JSON output (exit 0 when no errors) easyp validate-config"},{"id":"cli/configuration/configuration::command-specific-flags::30","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags Validate a different file with text output (global --format) easyp --format text validate-config --config example.easyp.yaml ```","content":"Command-Specific Flags Validate a different file with text output (global --format) easyp --format text validate-config --config example.easyp.yaml ```"},{"id":"cli/configuration/configuration::command-specific-flags::31","title":"EasyP Configuration Reference","section":"Command-Specific Flags","path":"/docs/guide/cli/configuration/configuration#command-specific-flags","headings":["Command-Specific Flags"],"excerpt":"Command-Specific Flags **Package management commands:**","content":"Command-Specific Flags **Package management commands:**"},{"id":"cli/configuration/configuration::easyp-mod-download::32","title":"EasyP Configuration Reference","section":"easyp mod download","path":"/docs/guide/cli/configuration/configuration#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Downloads dependencies based on lock file priority:","content":"easyp mod download Downloads dependencies based on lock file priority:"},{"id":"cli/configuration/configuration::easyp-mod-download::33","title":"EasyP Configuration Reference","section":"easyp mod download","path":"/docs/guide/cli/configuration/configuration#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **If easyp.lock exists** - downloads exact versions from lock file **If easyp.lock is missing** - downloads versions from easyp.yaml and creates easyp.lock","content":"easyp mod download **If easyp.lock exists** - downloads exact versions from lock file **If easyp.lock is missing** - downloads versions from easyp.yaml and creates easyp.lock"},{"id":"cli/configuration/configuration::easyp-mod-update::34","title":"EasyP Configuration Reference","section":"easyp mod update","path":"/docs/guide/cli/configuration/configuration#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Always downloads dependencies from easyp.yaml, ignoring existing lock file:","content":"easyp mod update Always downloads dependencies from easyp.yaml, ignoring existing lock file:"},{"id":"cli/configuration/configuration::easyp-mod-update::35","title":"EasyP Configuration Reference","section":"easyp mod update","path":"/docs/guide/cli/configuration/configuration#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update **Ignores easyp.lock** completely **Downloads versions from easyp.yaml** **Creates/updates easyp.lock** with new versions","content":"easyp mod update **Ignores easyp.lock** completely **Downloads versions from easyp.yaml** **Creates/updates easyp.lock** with new versions"},{"id":"cli/configuration/configuration::easyp-mod-vendor::36","title":"EasyP Configuration Reference","section":"easyp mod vendor","path":"/docs/guide/cli/configuration/configuration#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Copies proto files from dependencies to local vendor/ directory (similar to go mod vendor).","content":"easyp mod vendor Copies proto files from dependencies to local vendor/ directory (similar to go mod vendor)."},{"id":"cli/configuration/configuration::easyp-mod-vendor::37","title":"EasyP Configuration Reference","section":"easyp mod vendor","path":"/docs/guide/cli/configuration/configuration#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor No additional flags. Uses global --cfg flag for configuration.","content":"easyp mod vendor No additional flags. Uses global --cfg flag for configuration."},{"id":"cli/configuration/configuration::environment-variables::38","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables EasyP supports environment variables for configuration:","content":"Environment Variables EasyP supports environment variables for configuration:"},{"id":"cli/configuration/configuration::environment-variables::39","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Variable Description Default ---------- ------------- --------- EASYP_CFG Path to configuration file easyp.yaml EASYP_DEBUG Enable debug logging false EASYPPATH Cache and modules storage directory $","content":"Environment Variables Variable Description Default ---------- ------------- --------- EASYP_CFG Path to configuration file easyp.yaml EASYP_DEBUG Enable debug logging false EASYPPATH Cache and modules storage directory $HOME/.easyp EASYP_FORMAT Output format for supported commands (text/json). If not set, each command uses its own default. command-specific default EASYP_ROOT_GENERATE_PATH Root path for generate command . EASYP_INIT_DIR Directory for init command ."},{"id":"cli/configuration/configuration::environment-variables::40","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables **Examples:** ```bash Custom cache directory export EASYPPATH=/tmp/easyp-cache easyp mod download","content":"Environment Variables **Examples:** ```bash Custom cache directory export EASYPPATH=/tmp/easyp-cache easyp mod download"},{"id":"cli/configuration/configuration::environment-variables::41","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Debug mode via environment export EASYP_DEBUG=true easyp lint","content":"Environment Variables Debug mode via environment export EASYP_DEBUG=true easyp lint"},{"id":"cli/configuration/configuration::environment-variables::42","title":"EasyP Configuration Reference","section":"Environment Variables","path":"/docs/guide/cli/configuration/configuration#environment-variables","headings":["Environment Variables"],"excerpt":"Environment Variables Custom config file export EASYP_CFG=config/easyp.yaml easyp generate ```","content":"Environment Variables Custom config file export EASYP_CFG=config/easyp.yaml easyp generate ```"},{"id":"cli/configuration/configuration::configuration-file::43","title":"EasyP Configuration Reference","section":"Configuration File","path":"/docs/guide/cli/configuration/configuration#configuration-file","headings":["Configuration File"],"excerpt":"Configuration File The easyp.yaml file is the main configuration file for EasyP, defining how your proto files are linted, generated, and managed. This file is typically placed at the root of your project alongside your ","content":"Configuration File The easyp.yaml file is the main configuration file for EasyP, defining how your proto files are linted, generated, and managed. This file is typically placed at the root of your project alongside your proto files."},{"id":"cli/configuration/configuration::configuration-format::44","title":"EasyP Configuration Reference","section":"Configuration Format","path":"/docs/guide/cli/configuration/configuration#configuration-format","headings":["Configuration Format"],"excerpt":"Configuration Format EasyP supports both YAML and JSON configuration formats:","content":"Configuration Format EasyP supports both YAML and JSON configuration formats:"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::45","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration EasyP supports environment variable expansion directly in the easyp.yaml configuration file. This allows you to use environment variables for dynamic configuration values.","content":"Environment Variables in Configuration EasyP supports environment variable expansion directly in the easyp.yaml configuration file. This allows you to use environment variables for dynamic configuration values."},{"id":"cli/configuration/configuration::environment-variables-in-configuration::46","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Example with all supported features:** ```yaml deps: # Basic expansion: ${VAR} - expands to the value of VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Default value: ${VAR:-def","content":"Environment Variables in Configuration **Example with all supported features:** ```yaml deps: # Basic expansion: ${VAR} - expands to the value of VAR - ${GOOGLEAPIS_REPO}@${GOOGLEAPIS_VERSION} # Default value: ${VAR:-default} - uses default if VAR is unset or empty - ${GNOSTIC_REPO:-github.com/google/gnostic}@${GNOSTIC_VERSION:-v0.7.0}"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::47","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration generate: inputs: # Default value if INPUT_DIR is not set - directory: ${INPUT_DIR:-proto} plugins: - name: go # Basic expansion out: ${OUTPUT_DIR} opts: # Default value module: ${M","content":"Environment Variables in Configuration generate: inputs: # Default value if INPUT_DIR is not set - directory: ${INPUT_DIR:-proto} plugins: - name: go # Basic expansion out: ${OUTPUT_DIR} opts: # Default value module: ${MODULE_NAME:-github.com/example/project} timeout: ${TIMEOUT:-30} # Escaping: $$ becomes literal $, $${VAR} becomes literal ${VAR} path: \"${BASE_DIR}/$${TEMP}/file\" # Result: \"/tmp/${TEMP}/file\" (if BASE_DIR=/tmp) literal: \"$$\" # Result: \"$\" ```"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::48","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Supported syntax:** ${VAR} - expands to the value of VAR ${VAR:-default} - uses default if VAR is unset or empty ${VAR:=default} - uses default if VAR is unset or empty ${VAR-defa","content":"Environment Variables in Configuration **Supported syntax:** ${VAR} - expands to the value of VAR ${VAR:-default} - uses default if VAR is unset or empty ${VAR:=default} - uses default if VAR is unset or empty ${VAR-default} - uses default if VAR is unset (empty string is kept) $${VAR} or $$VAR - escapes to literal ${VAR} or $VAR $$ - escapes to literal $"},{"id":"cli/configuration/configuration::environment-variables-in-configuration::49","title":"EasyP Configuration Reference","section":"Environment Variables in Configuration","path":"/docs/guide/cli/configuration/configuration#environment-variables-in-configuration","headings":["Environment Variables in Configuration"],"excerpt":"Environment Variables in Configuration **Note:** Environment variables are expanded before YAML parsing, so any ${STRING} pattern will be processed. Use $$ to escape dollar signs when you need literal values.","content":"Environment Variables in Configuration **Note:** Environment variables are expanded before YAML parsing, so any ${STRING} pattern will be processed. Use $$ to escape dollar signs when you need literal values."},{"id":"cli/configuration/configuration::version::50","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Optional (legacy compatibility).** This field is accepted for backward compatibility and can be omitted in new configs.","content":"version **Optional (legacy compatibility).** This field is accepted for backward compatibility and can be omitted in new configs."},{"id":"cli/configuration/configuration::version::51","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version **Type:** string **Default:** omitted **Recommendation:** if you keep it, use v1alpha","content":"version **Type:** string **Default:** omitted **Recommendation:** if you keep it, use v1alpha"},{"id":"cli/configuration/configuration::version::52","title":"EasyP Configuration Reference","section":"version","path":"/docs/guide/cli/configuration/configuration#version","headings":["version"],"excerpt":"version The runtime behavior does not depend on this field.","content":"version The runtime behavior does not depend on this field."},{"id":"cli/configuration/configuration::lint::53","title":"EasyP Configuration Reference","section":"lint","path":"/docs/guide/cli/configuration/configuration#lint","headings":["lint"],"excerpt":"lint **Optional.** Configures proto file linting rules and behavior.","content":"lint **Optional.** Configures proto file linting rules and behavior."},{"id":"cli/configuration/configuration::lint::54","title":"EasyP Configuration Reference","section":"lint","path":"/docs/guide/cli/configuration/configuration#lint","headings":["lint"],"excerpt":"lint **Type:** object **Default:** Empty (no linting rules applied)","content":"lint **Type:** object **Default:** Empty (no linting rules applied)"},{"id":"cli/configuration/configuration::lintuse::55","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Optional.** Specifies which linter rules or rule categories to apply.","content":"lint.use **Optional.** Specifies which linter rules or rule categories to apply."},{"id":"cli/configuration/configuration::lintuse::56","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Type:** []string **Default:** [] (no rules)","content":"lint.use **Type:** []string **Default:** [] (no rules)"},{"id":"cli/configuration/configuration::lintuse::57","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Available categories:** MINIMAL - Essential package consistency checks BASIC - Naming conventions and common patterns DEFAULT - Additional recommended rules COMMENTS - Comment requirements UNARY_RPC - Streamin","content":"lint.use **Available categories:** MINIMAL - Essential package consistency checks BASIC - Naming conventions and common patterns DEFAULT - Additional recommended rules COMMENTS - Comment requirements UNARY_RPC - Streaming RPC restrictions"},{"id":"cli/configuration/configuration::lintuse::58","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **Individual rules:** Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"lint.use **Individual rules:** Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/configuration/configuration::lintuse::59","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **MINIMAL:** DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY","content":"lint.use **MINIMAL:** DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY"},{"id":"cli/configuration/configuration::lintuse::60","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **BASIC:** ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PAC","content":"lint.use **BASIC:** ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNAKE_CASE PACKAGE_SAME_CSHARP_NAMESPACE PACKAGE_SAME_GO_PACKAGE PACKAGE_SAME_JAVA_MULTIPLE_FILES PACKAGE_SAME_JAVA_PACKAGE PACKAGE_SAME_PHP_NAMESPACE PACKAGE_SAME_RUBY_PACKAGE PACKAGE_SAME_SWIFT_PREFIX RPC_PASCAL_CASE SERVICE_PASCAL_CASE"},{"id":"cli/configuration/configuration::lintuse::61","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **DEFAULT:** ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX","content":"lint.use **DEFAULT:** ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX"},{"id":"cli/configuration/configuration::lintuse::62","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **COMMENTS:** COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE","content":"lint.use **COMMENTS:** COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE"},{"id":"cli/configuration/configuration::lintuse::63","title":"EasyP Configuration Reference","section":"lint.use","path":"/docs/guide/cli/configuration/configuration#lintuse","headings":["lint.use"],"excerpt":"lint.use **UNARY_RPC:** RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING","content":"lint.use **UNARY_RPC:** RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING"},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::64","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix **Optional.** Specifies the required suffix for enum zero values.","content":"lint.enum_zero_value_suffix **Optional.** Specifies the required suffix for enum zero values."},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::65","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"lint.enum_zero_value_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/configuration/configuration::lintenum_zero_value_suffix::66","title":"EasyP Configuration Reference","section":"lint.enum_zero_value_suffix","path":"/docs/guide/cli/configuration/configuration#lintenum_zero_value_suffix","headings":["lint.enum_zero_value_suffix"],"excerpt":"lint.enum_zero_value_suffix This enforces enum zero values like:","content":"lint.enum_zero_value_suffix This enforces enum zero values like:"},{"id":"cli/configuration/configuration::lintservice_suffix::67","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix **Optional.** Specifies the required suffix for service names.","content":"lint.service_suffix **Optional.** Specifies the required suffix for service names."},{"id":"cli/configuration/configuration::lintservice_suffix::68","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"Service\", \"API\", \"Svc\"","content":"lint.service_suffix **Type:** string **Default:** \"\" (no suffix required) **Common values:** \"Service\", \"API\", \"Svc\""},{"id":"cli/configuration/configuration::lintservice_suffix::69","title":"EasyP Configuration Reference","section":"lint.service_suffix","path":"/docs/guide/cli/configuration/configuration#lintservice_suffix","headings":["lint.service_suffix"],"excerpt":"lint.service_suffix This enforces service names like:","content":"lint.service_suffix This enforces service names like:"},{"id":"cli/configuration/configuration::lintignore::70","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore **Optional.** Directories or files to exclude from all linting rules.","content":"lint.ignore **Optional.** Directories or files to exclude from all linting rules."},{"id":"cli/configuration/configuration::lintignore::71","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore **Type:** []string **Default:** []","content":"lint.ignore **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::lintignore::72","title":"EasyP Configuration Reference","section":"lint.ignore","path":"/docs/guide/cli/configuration/configuration#lintignore","headings":["lint.ignore"],"excerpt":"lint.ignore Paths are relative to the easyp.yaml file location. Supports glob patterns.","content":"lint.ignore Paths are relative to the easyp.yaml file location. Supports glob patterns."},{"id":"cli/configuration/configuration::lintexcept::73","title":"EasyP Configuration Reference","section":"lint.except","path":"/docs/guide/cli/configuration/configuration#lintexcept","headings":["lint.except"],"excerpt":"lint.except **Optional.** Disables specific rules globally across the entire project.","content":"lint.except **Optional.** Disables specific rules globally across the entire project."},{"id":"cli/configuration/configuration::lintexcept::74","title":"EasyP Configuration Reference","section":"lint.except","path":"/docs/guide/cli/configuration/configuration#lintexcept","headings":["lint.except"],"excerpt":"lint.except **Type:** []string **Default:** []","content":"lint.except **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::lintallow_comment_ignores::75","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores **Optional.** Enables inline comment-based rule ignoring within proto files.","content":"lint.allow_comment_ignores **Optional.** Enables inline comment-based rule ignoring within proto files."},{"id":"cli/configuration/configuration::lintallow_comment_ignores::76","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores **Type:** boolean **Default:** false","content":"lint.allow_comment_ignores **Type:** boolean **Default:** false"},{"id":"cli/configuration/configuration::lintallow_comment_ignores::77","title":"EasyP Configuration Reference","section":"lint.allow_comment_ignores","path":"/docs/guide/cli/configuration/configuration#lintallow_comment_ignores","headings":["lint.allow_comment_ignores"],"excerpt":"lint.allow_comment_ignores When enabled, allows comments like:","content":"lint.allow_comment_ignores When enabled, allows comments like:"},{"id":"cli/configuration/configuration::lintignore_only::78","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Optional.** Disables specific rules only for certain files or directories.","content":"lint.ignore_only **Optional.** Disables specific rules only for certain files or directories."},{"id":"cli/configuration/configuration::lintignore_only::79","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Type:** mapstringstring **Default:** {}","content":"lint.ignore_only **Type:** mapstringstring **Default:** {}"},{"id":"cli/configuration/configuration::lintignore_only::80","title":"EasyP Configuration Reference","section":"lint.ignore_only","path":"/docs/guide/cli/configuration/configuration#lintignore_only","headings":["lint.ignore_only"],"excerpt":"lint.ignore_only **Key:** Rule name or category **Value:** Array of file paths or directories","content":"lint.ignore_only **Key:** Rule name or category **Value:** Array of file paths or directories"},{"id":"cli/configuration/configuration::deps::81","title":"EasyP Configuration Reference","section":"deps","path":"/docs/guide/cli/configuration/configuration#deps","headings":["deps"],"excerpt":"deps **Optional.** Lists external proto dependencies to download and manage.","content":"deps **Optional.** Lists external proto dependencies to download and manage."},{"id":"cli/configuration/configuration::deps::82","title":"EasyP Configuration Reference","section":"deps","path":"/docs/guide/cli/configuration/configuration#deps","headings":["deps"],"excerpt":"deps **Type:** []string **Default:** []","content":"deps **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::dependency-format::83","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format Dependencies follow the format: $GIT_LINK@$VERSION","content":"Dependency Format Dependencies follow the format: $GIT_LINK@$VERSION"},{"id":"cli/configuration/configuration::dependency-format::84","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Components:** $GIT_LINK - Git repository URL (GitHub, GitLab, etc.) $VERSION - Git tag or full commit hash (optional)","content":"Dependency Format **Components:** $GIT_LINK - Git repository URL (GitHub, GitLab, etc.) $VERSION - Git tag or full commit hash (optional)"},{"id":"cli/configuration/configuration::dependency-format::85","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Format variations:** owner/repo - Latest commit from default branch owner/repo@v1.0.0 - Specific git tag owner/repo@47b927cbb41c4fdea1292baf - Full commit hash github.com/owner/repo@version - Full URL","content":"Dependency Format **Format variations:** owner/repo - Latest commit from default branch owner/repo@v1.0.0 - Specific git tag owner/repo@47b927cbb41c4fdea1292baf - Full commit hash github.com/owner/repo@version - Full URL with version gitlab.com/group/repo@tag - GitLab repository"},{"id":"cli/configuration/configuration::dependency-format::86","title":"EasyP Configuration Reference","section":"Dependency Format","path":"/docs/guide/cli/configuration/configuration#dependency-format","headings":["Dependency Format"],"excerpt":"Dependency Format **Note:** If @$VERSION is omitted, EasyP downloads the latest commit from the repository's default branch.","content":"Dependency Format **Note:** If @$VERSION is omitted, EasyP downloads the latest commit from the repository's default branch."},{"id":"cli/configuration/configuration::generate::87","title":"EasyP Configuration Reference","section":"generate","path":"/docs/guide/cli/configuration/configuration#generate","headings":["generate"],"excerpt":"generate **Optional.** Configures code generation from proto files.","content":"generate **Optional.** Configures code generation from proto files."},{"id":"cli/configuration/configuration::generate::88","title":"EasyP Configuration Reference","section":"generate","path":"/docs/guide/cli/configuration/configuration#generate","headings":["generate"],"excerpt":"generate **Type:** object **Default:** {}","content":"generate **Type:** object **Default:** {}"},{"id":"cli/configuration/configuration::generateinputs::89","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Required when generate is set.** Specifies sources of proto files for generation.","content":"generate.inputs **Required when generate is set.** Specifies sources of proto files for generation."},{"id":"cli/configuration/configuration::generateinputs::90","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Type:** []object (minimum 1 item) **Default:** not set","content":"generate.inputs **Type:** []object (minimum 1 item) **Default:** not set"},{"id":"cli/configuration/configuration::generateinputs::91","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs ```yaml generate: inputs: # Local directory - directory: \"proto\"","content":"generate.inputs ```yaml generate: inputs: # Local directory - directory: \"proto\""},{"id":"cli/configuration/configuration::generateinputs::92","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs Local directory with advanced options - directory: path: \"api/proto\" root: \".\"","content":"generate.inputs Local directory with advanced options - directory: path: \"api/proto\" root: \".\""},{"id":"cli/configuration/configuration::generateinputs::93","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs Remote git repository - git_repo: url: \"github.com/acme/common@v1.0.0\" sub_directory: \"proto\" root: \".\" ```","content":"generate.inputs Remote git repository - git_repo: url: \"github.com/acme/common@v1.0.0\" sub_directory: \"proto\" root: \".\" ```"},{"id":"cli/configuration/configuration::generateinputs::94","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Directory input fields:** directory (string or object) - Local directory path directory.path (string) - Directory path directory.root (string) - Root path for import resolution (default: \".\")","content":"generate.inputs **Directory input fields:** directory (string or object) - Local directory path directory.path (string) - Directory path directory.root (string) - Root path for import resolution (default: \".\")"},{"id":"cli/configuration/configuration::generateinputs::95","title":"EasyP Configuration Reference","section":"generate.inputs","path":"/docs/guide/cli/configuration/configuration#generateinputs","headings":["generate.inputs"],"excerpt":"generate.inputs **Git repository input fields:** git_repo.url (string) - Repository URL with optional version git_repo.sub_directory (string) - Subdirectory within the repository git_repo.root (string) - Root path used f","content":"generate.inputs **Git repository input fields:** git_repo.url (string) - Repository URL with optional version git_repo.sub_directory (string) - Subdirectory within the repository git_repo.root (string) - Root path used for import resolution"},{"id":"cli/configuration/configuration::generateplugins::96","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Required when generate is set.** Configures protoc plugins for code generation.","content":"generate.plugins **Required when generate is set.** Configures protoc plugins for code generation."},{"id":"cli/configuration/configuration::generateplugins::97","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Type:** []object (minimum 1 item) **Default:** not set","content":"generate.plugins **Type:** []object (minimum 1 item) **Default:** not set"},{"id":"cli/configuration/configuration::generateplugins::98","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins ```yaml generate: plugins: # Local plugin - name: go out: . opts: paths: source_relative","content":"generate.plugins ```yaml generate: plugins: # Local plugin - name: go out: . opts: paths: source_relative"},{"id":"cli/configuration/configuration::generateplugins::99","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Remote plugin - remote: \"buf.build/bufbuild/protovalidate-go:v0.4.0\" out: gen/go opts: paths: source_relative","content":"generate.plugins Remote plugin - remote: \"buf.build/bufbuild/protovalidate-go:v0.4.0\" out: gen/go opts: paths: source_relative"},{"id":"cli/configuration/configuration::generateplugins::100","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Plugin with import dependencies - name: grpc-gateway out: . with_imports: true opts: paths: source_relative ```","content":"generate.plugins Plugin with import dependencies - name: grpc-gateway out: . with_imports: true opts: paths: source_relative ```"},{"id":"cli/configuration/configuration::generateplugins::101","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Plugin fields:** name (string, optional) - Plugin name (omit protoc-gen- prefix) remote (string, optional) - Remote plugin URL for execution path (string, optional) - Path to plugin executable file com","content":"generate.plugins **Plugin fields:** name (string, optional) - Plugin name (omit protoc-gen- prefix) remote (string, optional) - Remote plugin URL for execution path (string, optional) - Path to plugin executable file command ([]string, optional) - Command to execute plugin out (string, optional) - Output directory for generated files; defaults to the resolved generate root opts (mapstring, optional) - Plugin-specific options; each key can be a single scalar value or an array of scalar values with_imports (boolean, optional) - Include imported dependencies"},{"id":"cli/configuration/configuration::generateplugins::102","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins Plugin source is one-of: exactly one of name, remote, path, or command must be set.","content":"generate.plugins Plugin source is one-of: exactly one of name, remote, path, or command must be set."},{"id":"cli/configuration/configuration::generateplugins::103","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins **Common plugin options:** ```yaml Go plugin options opts: paths: source_relative # Generate files relative to input module: github.com/acme/api # Go module path","content":"generate.plugins **Common plugin options:** ```yaml Go plugin options opts: paths: source_relative # Generate files relative to input module: github.com/acme/api # Go module path"},{"id":"cli/configuration/configuration::generateplugins::104","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins gRPC Gateway options opts: paths: source_relative grpc_api_configuration: api.yaml # gRPC API configuration","content":"generate.plugins gRPC Gateway options opts: paths: source_relative grpc_api_configuration: api.yaml # gRPC API configuration"},{"id":"cli/configuration/configuration::generateplugins::105","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins OpenAPI v2 options opts: simple_operation_ids: true # Use simple operation IDs generate_unbound_methods: false # Skip unbound methods","content":"generate.plugins OpenAPI v2 options opts: simple_operation_ids: true # Use simple operation IDs generate_unbound_methods: false # Skip unbound methods"},{"id":"cli/configuration/configuration::generateplugins::106","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins ts-proto options with repeated key values opts: env: node outputServices: - grpc-js - generic-definitions ```","content":"generate.plugins ts-proto options with repeated key values opts: env: node outputServices: - grpc-js - generic-definitions ```"},{"id":"cli/configuration/configuration::generateplugins::107","title":"EasyP Configuration Reference","section":"generate.plugins","path":"/docs/guide/cli/configuration/configuration#generateplugins","headings":["generate.plugins"],"excerpt":"generate.plugins When an opts value is a list, EasyP serializes it as repeated plugin params, e.g. outputServices=grpc-js,outputServices=generic-definitions.","content":"generate.plugins When an opts value is a list, EasyP serializes it as repeated plugin params, e.g. outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/configuration/configuration::breaking::108","title":"EasyP Configuration Reference","section":"breaking","path":"/docs/guide/cli/configuration/configuration#breaking","headings":["breaking"],"excerpt":"breaking **Optional.** Configures backward compatibility checking.","content":"breaking **Optional.** Configures backward compatibility checking."},{"id":"cli/configuration/configuration::breaking::109","title":"EasyP Configuration Reference","section":"breaking","path":"/docs/guide/cli/configuration/configuration#breaking","headings":["breaking"],"excerpt":"breaking **Type:** object **Default:** {}","content":"breaking **Type:** object **Default:** {}"},{"id":"cli/configuration/configuration::breakingignore::110","title":"EasyP Configuration Reference","section":"breaking.ignore","path":"/docs/guide/cli/configuration/configuration#breakingignore","headings":["breaking.ignore"],"excerpt":"breaking.ignore **Optional.** Directories or files to exclude from breaking change detection.","content":"breaking.ignore **Optional.** Directories or files to exclude from breaking change detection."},{"id":"cli/configuration/configuration::breakingignore::111","title":"EasyP Configuration Reference","section":"breaking.ignore","path":"/docs/guide/cli/configuration/configuration#breakingignore","headings":["breaking.ignore"],"excerpt":"breaking.ignore **Type:** []string **Default:** []","content":"breaking.ignore **Type:** []string **Default:** []"},{"id":"cli/configuration/configuration::breakingagainst_git_ref::112","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref **Optional.** Git reference (branch, tag, or commit) to compare against for breaking changes.","content":"breaking.against_git_ref **Optional.** Git reference (branch, tag, or commit) to compare against for breaking changes."},{"id":"cli/configuration/configuration::breakingagainst_git_ref::113","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref **Type:** string **Default:** \"\" (falls back to CLI --against default: master)","content":"breaking.against_git_ref **Type:** string **Default:** \"\" (falls back to CLI --against default: master)"},{"id":"cli/configuration/configuration::breakingagainst_git_ref::114","title":"EasyP Configuration Reference","section":"breaking.against_git_ref","path":"/docs/guide/cli/configuration/configuration#breakingagainst_git_ref","headings":["breaking.against_git_ref"],"excerpt":"breaking.against_git_ref Can be overridden by the --against CLI flag.","content":"breaking.against_git_ref Can be overridden by the --against CLI flag."},{"id":"cli/configuration/configuration::configuration-validation::115","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation EasyP validates configuration files on startup and provides helpful error messages:","content":"Configuration Validation EasyP validates configuration files on startup and provides helpful error messages:"},{"id":"cli/configuration/configuration::configuration-validation::116","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation ```bash Invalid rule name Error: invalid rule: INVALID_RULE_NAME","content":"Configuration Validation ```bash Invalid rule name Error: invalid rule: INVALID_RULE_NAME"},{"id":"cli/configuration/configuration::configuration-validation::117","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Missing required field in generate section Error: required field \"plugins\" is missing (path: generate.plugins)","content":"Configuration Validation Missing required field in generate section Error: required field \"plugins\" is missing (path: generate.plugins)"},{"id":"cli/configuration/configuration::configuration-validation::118","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Invalid dependency format Error: invalid dependency format: invalid-repo-url ```","content":"Configuration Validation Invalid dependency format Error: invalid dependency format: invalid-repo-url ```"},{"id":"cli/configuration/configuration::configuration-validation::119","title":"EasyP Configuration Reference","section":"Configuration Validation","path":"/docs/guide/cli/configuration/configuration#configuration-validation","headings":["Configuration Validation"],"excerpt":"Configuration Validation Use easyp --debug for detailed validation information.","content":"Configuration Validation Use easyp --debug for detailed validation information."},{"id":"cli/configuration/configuration::migration-from-buf::120","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf EasyP is fully compatible with Buf configurations. To migrate:","content":"Migration from Buf EasyP is fully compatible with Buf configurations. To migrate:"},{"id":"cli/configuration/configuration::migration-from-buf::121","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf Place buf.yaml or buf.yml in the project root Run easyp init and confirm migration when prompted Update deps format if using BSR modules Review migrated lint/breaking settings and adjust as needed","content":"Migration from Buf Place buf.yaml or buf.yml in the project root Run easyp init and confirm migration when prompted Update deps format if using BSR modules Review migrated lint/breaking settings and adjust as needed"},{"id":"cli/configuration/configuration::migration-from-buf::122","title":"EasyP Configuration Reference","section":"Migration from Buf","path":"/docs/guide/cli/configuration/configuration#migration-from-buf","headings":["Migration from Buf"],"excerpt":"Migration from Buf Most Buf configurations work without changes in EasyP.","content":"Migration from Buf Most Buf configurations work without changes in EasyP."},{"id":"cli/generator/examples/go::installing-plugins::0","title":"Go","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/go#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins First, install the necessary plugins for working with gRPC:","content":"Installing Plugins First, install the necessary plugins for working with gRPC:"},{"id":"cli/generator/examples/go::installing-plugins::1","title":"Go","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/go#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc plugins for use with EasyP.","content":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc plugins for use with EasyP."},{"id":"cli/generator/examples/go::example-proto-service::2","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is an example proto file for an Echo service:","content":"Example Proto Service Here is an example proto file for an Echo service:"},{"id":"cli/generator/examples/go::example-proto-service::3","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/go::example-proto-service::4","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/go::example-proto-service::5","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/go::example-proto-service::6","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/go::example-proto-service::7","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::example-proto-service::8","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; }","content":"Example Proto Service message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/go::example-proto-service::9","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamRequest { string payload = 1; }","content":"Example Proto Service message EchoStreamRequest { string payload = 1; }"},{"id":"cli/generator/examples/go::example-proto-service::10","title":"Go","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/go#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```","content":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/go::configuration-setup::11","title":"Go","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/go#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Create and configure the easyp.yaml configuration file:","content":"Configuration Setup Create and configure the easyp.yaml configuration file:"},{"id":"cli/generator/examples/go::configuration-setup::12","title":"Go","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/go#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup This file specifies that two plugins will be used: go for generating Go code and go-grpc for generating gRPC code, along with their respective options.","content":"Configuration Setup This file specifies that two plugins will be used: go for generating Go code and go-grpc for generating gRPC code, along with their respective options."},{"id":"cli/generator/examples/go::generating-code::13","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate code, use the following command:","content":"Generating Code To generate code, use the following command:"},{"id":"cli/generator/examples/go::generating-code::14","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/go::generating-code::15","title":"Go","section":"Generating Code","path":"/docs/guide/cli/generator/examples/go#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go code, which you can interact with directly.","content":"Generating Code Now you have the generated Go code, which you can interact with directly."},{"id":"cli/generator/examples/grpc-gateway::installing-plugins::0","title":"gRPC-Gateway","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/grpc-gateway#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins In addition to the plugins for working with gRPC, you also need to install the following plugins for gRPC-Gateway:","content":"Installing Plugins In addition to the plugins for working with gRPC, you also need to install the following plugins for gRPC-Gateway:"},{"id":"cli/generator/examples/grpc-gateway::installing-plugins::1","title":"gRPC-Gateway","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/grpc-gateway#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2, and protoc-gen-grpc-gateway plugins for use with EasyP`.","content":"Installing Plugins These commands will install the protoc-gen-go, protoc-gen-go-grpc, protoc-gen-openapiv2, and protoc-gen-grpc-gateway plugins for use with EasyP`."},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::2","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is the initial proto file for an Echo service:","content":"Example Proto Service Here is the initial proto file for an Echo service:"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::3","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::4","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::5","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::6","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::7","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::8","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; } ```","content":"Example Proto Service message EchoResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::9","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service To use gRPC-Gateway, update the proto file to include HTTP options:","content":"Example Proto Service To use gRPC-Gateway, update the proto file to include HTTP options:"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::10","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\"; import \"google/api/annotations.proto\";","content":"Example Proto Service ```proto syntax = \"proto3\"; import \"google/api/annotations.proto\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::11","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::12","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::13","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse) { option (google.api.http) = { // [!code ++] post: \"/api/v1/echo\" // [!code ++] body: \"*\" // [!code ++] }; // [!code ++] } }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::14","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1; }","content":"Example Proto Service message EchoRequest { string payload = 1; }"},{"id":"cli/generator/examples/grpc-gateway::example-proto-service::15","title":"gRPC-Gateway","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/grpc-gateway#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; } ```","content":"Example Proto Service message EchoResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::16","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Update your easyp.yaml configuration file to include the necessary dependencies and plugins:","content":"Configuration Setup Update your easyp.yaml configuration file to include the necessary dependencies and plugins:"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::17","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup ```yaml deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]","content":"Configuration Setup ```yaml deps: # [!code ++] - github.com/googleapis/googleapis # [!code ++]"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::18","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: grpc-gateway # [!code ++] out: . # [!","content":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: grpc-gateway # [!code ++] out: . # [!code ++] opts: # [!code ++] paths: source_relative # [!code ++] - name: openapiv2 # [!code ++] out: . # [!code ++] opts: # [!code ++] simple_operation_ids: false # [!code ++] generate_unbound_methods: false # [!code ++] ```"},{"id":"cli/generator/examples/grpc-gateway::configuration-setup::19","title":"gRPC-Gateway","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/grpc-gateway#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup The deps section lists dependencies required for proto file imports. In this case, we add github.com/googleapis/googleapis because it contains the annotations.proto file used in the proto service defi","content":"Configuration Setup The deps section lists dependencies required for proto file imports. In this case, we add github.com/googleapis/googleapis because it contains the annotations.proto file used in the proto service definition."},{"id":"cli/generator/examples/grpc-gateway::updating-dependencies::20","title":"gRPC-Gateway","section":"Updating Dependencies","path":"/docs/guide/cli/generator/examples/grpc-gateway#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies After updating your configuration file, run the following command to download the specified dependencies:","content":"Updating Dependencies After updating your configuration file, run the following command to download the specified dependencies:"},{"id":"cli/generator/examples/grpc-gateway::updating-dependencies::21","title":"gRPC-Gateway","section":"Updating Dependencies","path":"/docs/guide/cli/generator/examples/grpc-gateway#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies For more details on managing dependencies, refer to the Package Manager section.","content":"Updating Dependencies For more details on managing dependencies, refer to the Package Manager section."},{"id":"cli/generator/examples/grpc-gateway::generating-code::22","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate the code, use the following command:","content":"Generating Code To generate the code, use the following command:"},{"id":"cli/generator/examples/grpc-gateway::generating-code::23","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/grpc-gateway::generating-code::24","title":"gRPC-Gateway","section":"Generating Code","path":"/docs/guide/cli/generator/examples/grpc-gateway#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go and gRPC-Gateway code, which you can interact with directly.","content":"Generating Code Now you have the generated Go and gRPC-Gateway code, which you can interact with directly."},{"id":"cli/generator/examples/validate::installing-plugins::0","title":"Validate","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/validate#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins First, install the necessary plugins for working with gRPC:","content":"Installing Plugins First, install the necessary plugins for working with gRPC:"},{"id":"cli/generator/examples/validate::installing-plugins::1","title":"Validate","section":"Installing Plugins","path":"/docs/guide/cli/generator/examples/validate#installing-plugins","headings":["Installing Plugins"],"excerpt":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc and protoc-gen-validate plugins for use with EasyP.","content":"Installing Plugins These commands will install the protoc-gen-go and protoc-gen-go-grpc and protoc-gen-validate plugins for use with EasyP."},{"id":"cli/generator/examples/validate::example-proto-service::2","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service Here is an example proto file for an Echo service:","content":"Example Proto Service Here is an example proto file for an Echo service:"},{"id":"cli/generator/examples/validate::example-proto-service::3","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service ```proto syntax = \"proto3\";","content":"Example Proto Service ```proto syntax = \"proto3\";"},{"id":"cli/generator/examples/validate::example-proto-service::4","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service package api.echo.v1;","content":"Example Proto Service package api.echo.v1;"},{"id":"cli/generator/examples/validate::example-proto-service::5","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service import \"validate/validate.proto\";","content":"Example Proto Service import \"validate/validate.proto\";"},{"id":"cli/generator/examples/validate::example-proto-service::6","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";","content":"Example Proto Service option go_package = \"github.com/easyp-tech/example/api/echo/v1;pb\";"},{"id":"cli/generator/examples/validate::example-proto-service::7","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }","content":"Example Proto Service service EchoAPI { rpc Echo(EchoRequest) returns (EchoResponse); rpc EchoStream(EchoStreamRequest) returns (EchoResponse); }"},{"id":"cli/generator/examples/validate::example-proto-service::8","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Example Proto Service message EchoRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::example-proto-service::9","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoResponse { string payload = 2; }","content":"Example Proto Service message EchoResponse { string payload = 2; }"},{"id":"cli/generator/examples/validate::example-proto-service::10","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }","content":"Example Proto Service message EchoStreamRequest { string payload = 1 [(validate.rules).string = {max_len: 200}]; }"},{"id":"cli/generator/examples/validate::example-proto-service::11","title":"Validate","section":"Example Proto Service","path":"/docs/guide/cli/generator/examples/validate#example-proto-service","headings":["Example Proto Service"],"excerpt":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```","content":"Example Proto Service message EchoStreamResponse { string payload = 2; } ```"},{"id":"cli/generator/examples/validate::configuration-setup::12","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup Create and configure the easyp.yaml configuration file:","content":"Configuration Setup Create and configure the easyp.yaml configuration file:"},{"id":"cli/generator/examples/validate::configuration-setup::13","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]","content":"Configuration Setup ```yaml deps: # [!code ++] - github.com/bufbuild/protoc-gen-validate # [!code ++]"},{"id":"cli/generator/examples/validate::configuration-setup::14","title":"Validate","section":"Configuration Setup","path":"/docs/guide/cli/generator/examples/validate#configuration-setup","headings":["Configuration Setup"],"excerpt":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: validate out: . opts: paths: source_r","content":"Configuration Setup generate: plugins: - name: go out: . opts: paths: source_relative - name: go-grpc out: . opts: paths: source_relative require_unimplemented_servers: false - name: validate out: . opts: paths: source_relative lang: \"go\" ```"},{"id":"cli/generator/examples/validate::generating-code::15","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code To generate code, use the following command:","content":"Generating Code To generate code, use the following command:"},{"id":"cli/generator/examples/validate::generating-code::16","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:","content":"Generating Code If the --cfg flag is not specified, the easyp.yaml file in the current directory will be used by default:"},{"id":"cli/generator/examples/validate::generating-code::17","title":"Validate","section":"Generating Code","path":"/docs/guide/cli/generator/examples/validate#generating-code","headings":["Generating Code"],"excerpt":"Generating Code Now you have the generated Go code, which you can interact with directly.","content":"Generating Code Now you have the generated Go code, which you can interact with directly."},{"id":"cli/generator/generator::top::0","title":"Generator","path":"/docs/guide/cli/generator/generator","headings":[],"excerpt":"EasyP includes a powerful generator that simplifies the process of generating code from proto files. By using YAML configurations, EasyP makes this process more user-friendly and intuitive compared to using the protoc co","content":"EasyP includes a powerful generator that simplifies the process of generating code from proto files. By using YAML configurations, EasyP makes this process more user-friendly and intuitive compared to using the protoc command directly."},{"id":"cli/generator/generator::key-features-of-the-generator::1","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Simplified Code Generation**: - Generate code from proto files using a YAML configuration. - Avoid the need to write long and complex protoc commands.","content":"Key Features of the Generator **Simplified Code Generation**: - Generate code from proto files using a YAML configuration. - Avoid the need to write long and complex protoc commands."},{"id":"cli/generator/generator::key-features-of-the-generator::2","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Wrapper around protoc**: - EasyP functions as a wrapper around protoc, providing a more convenient API through configuration files. - Supports all options and plugins available in protoc.","content":"Key Features of the Generator **Wrapper around protoc**: - EasyP functions as a wrapper around protoc, providing a more convenient API through configuration files. - Supports all options and plugins available in protoc."},{"id":"cli/generator/generator::key-features-of-the-generator::3","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Flexibility and Customization**: - Use the same parameters as protoc plugins, directly in the configuration file. - Support for multiple plugins and their parameters in a single configurat","content":"Key Features of the Generator **Flexibility and Customization**: - Use the same parameters as protoc plugins, directly in the configuration file. - Support for multiple plugins and their parameters in a single configuration."},{"id":"cli/generator/generator::key-features-of-the-generator::4","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Generate Code from Multiple Sources**: - Generate code from local directories or remote repositories. - Easily integrate with existing projects and repositories.","content":"Key Features of the Generator **Generate Code from Multiple Sources**: - Generate code from local directories or remote repositories. - Easily integrate with existing projects and repositories."},{"id":"cli/generator/generator::key-features-of-the-generator::5","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Remote Generation**: - Generate code from remote Git repositories without local checkout.","content":"Key Features of the Generator **Remote Generation**: - Generate code from remote Git repositories without local checkout."},{"id":"cli/generator/generator::key-features-of-the-generator::6","title":"Generator","section":"Key Features of the Generator","path":"/docs/guide/cli/generator/generator#key-features-of-the-generator","headings":["Key Features of the Generator"],"excerpt":"Key Features of the Generator **Package Manager Integration**: - Seamless integration with EasyP's package manager for dependency management. - Automatic resolution and inclusion of proto dependencies.","content":"Key Features of the Generator **Package Manager Integration**: - Seamless integration with EasyP's package manager for dependency management. - Automatic resolution and inclusion of proto dependencies."},{"id":"cli/generator/generator::complete-configuration-example::7","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example ```yaml Package manager dependencies deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 - github.com/bufbuild/protoc-gen-validate@","content":"Complete Configuration Example ```yaml Package manager dependencies deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::complete-configuration-example::8","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Code generation configuration generate: inputs: # Local directory input - directory: path: \"proto\" root: \".\" # Remote Git repository input - git_repo: url: \"github.com/acme/weather@v1.2.3\" ","content":"Complete Configuration Example Code generation configuration generate: inputs: # Local directory input - directory: path: \"proto\" root: \".\" # Remote Git repository input - git_repo: url: \"github.com/acme/weather@v1.2.3\" sub_directory: \"proto/api\" # Another remote repository - git_repo: url: \"https://github.com/company/internal-protos.git\" sub_directory: \"definitions\" plugins: # Local plugin execution - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myproject with_imports: true # Local plugin with custom options - name: go-grpc out: ./gen/go opts: paths: source_relative require_unimplemented_servers: false"},{"id":"cli/generator/generator::complete-configuration-example::9","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example Managed mode - automatically set file and field options managed: enabled: true disable: - module: github.com/googleapis/googleapis # Disable for specific module override: - file_option: go_","content":"Complete Configuration Example Managed mode - automatically set file and field options managed: enabled: true disable: - module: github.com/googleapis/googleapis # Disable for specific module override: - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go - file_option: java_package_prefix value: com.mycompany - file_option: csharp_namespace_prefix value: MyCompany - field_option: jstype value: JS_STRING path: api/v1/ # Apply to specific path"},{"id":"cli/generator/generator::complete-configuration-example::10","title":"Generator","section":"Complete Configuration Example","path":"/docs/guide/cli/generator/generator#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example ```","content":"Complete Configuration Example ```"},{"id":"cli/generator/generator::local-directory-input::11","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Local directory input is the most common and straightforward way to specify proto files for generation. Use this when your proto files are already present in your project directory structure.","content":"Local Directory Input Local directory input is the most common and straightforward way to specify proto files for generation. Use this when your proto files are already present in your project directory structure."},{"id":"cli/generator/generator::local-directory-input::12","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **When to use:** Proto files are part of your project repository You need full control over proto file organization Working with a single service or application Proto files don't change frequently","content":"Local Directory Input **When to use:** Proto files are part of your project repository You need full control over proto file organization Working with a single service or application Proto files don't change frequently"},{"id":"cli/generator/generator::local-directory-input::13","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input The root parameter is particularly useful in monorepo setups where you need to control import path resolution. When root is set to a parent directory, import paths in your proto files will be resolv","content":"Local Directory Input The root parameter is particularly useful in monorepo setups where you need to control import path resolution. When root is set to a parent directory, import paths in your proto files will be resolved relative to that root, not the current working directory."},{"id":"cli/generator/generator::local-directory-input::14","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **Parameters:**","content":"Local Directory Input **Parameters:**"},{"id":"cli/generator/generator::local-directory-input::15","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- path string ✅ - Path to the directory containing proto files root string ❌ \".\" Root directory used f","content":"Local Directory Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- path string ✅ - Path to the directory containing proto files root string ❌ \".\" Root directory used for import path resolution"},{"id":"cli/generator/generator::local-directory-input::16","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input **Examples:**","content":"Local Directory Input **Examples:**"},{"id":"cli/generator/generator::local-directory-input::17","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input These examples show the difference between basic directory specification and advanced configuration with custom import resolution:","content":"Local Directory Input These examples show the difference between basic directory specification and advanced configuration with custom import resolution:"},{"id":"cli/generator/generator::local-directory-input::18","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input ```yaml Basic usage - Simple path specification inputs: - directory: \"api/proto\"","content":"Local Directory Input ```yaml Basic usage - Simple path specification inputs: - directory: \"api/proto\""},{"id":"cli/generator/generator::local-directory-input::19","title":"Generator","section":"Local Directory Input","path":"/docs/guide/cli/generator/generator#local-directory-input","headings":["Local Directory Input"],"excerpt":"Local Directory Input Advanced usage with custom root - Controls import path resolution inputs: - directory: path: \"services/auth/proto\" root: \"services/auth\" # Imports will be relative to this path ```","content":"Local Directory Input Advanced usage with custom root - Controls import path resolution inputs: - directory: path: \"services/auth/proto\" root: \"services/auth\" # Imports will be relative to this path ```"},{"id":"cli/generator/generator::remote-git-repository-input::20","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Remote Git repository input allows you to generate code from proto files hosted in external repositories without requiring a local checkout. This is particularly powerful for consuming APIs fr","content":"Remote Git Repository Input Remote Git repository input allows you to generate code from proto files hosted in external repositories without requiring a local checkout. This is particularly powerful for consuming APIs from other teams or external vendors."},{"id":"cli/generator/generator::remote-git-repository-input::21","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **When to use:** Consuming proto definitions from other teams or services Integrating with vendor APIs that provide proto definitions Working with shared proto libraries across multiple projec","content":"Remote Git Repository Input **When to use:** Consuming proto definitions from other teams or services Integrating with vendor APIs that provide proto definitions Working with shared proto libraries across multiple projects You want to ensure you're always using the correct version of external APIs"},{"id":"cli/generator/generator::remote-git-repository-input::22","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Recommended approach:** Always pin to specific versions in production (@v1.0.0, not latest) Use semantic versions when available for easier dependency management Prefer public tags over comm","content":"Remote Git Repository Input **Recommended approach:** Always pin to specific versions in production (@v1.0.0, not latest) Use semantic versions when available for easier dependency management Prefer public tags over commit hashes for better traceability"},{"id":"cli/generator/generator::remote-git-repository-input::23","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input The root parameter controls import resolution root for files from this repository.","content":"Remote Git Repository Input The root parameter controls import resolution root for files from this repository."},{"id":"cli/generator/generator::remote-git-repository-input::24","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Parameters:**","content":"Remote Git Repository Input **Parameters:**"},{"id":"cli/generator/generator::remote-git-repository-input::25","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- url string ✅ - Git repository URL with optional version/tag/commit sub_directory string ❌ \"\" S","content":"Remote Git Repository Input Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- url string ✅ - Git repository URL with optional version/tag/commit sub_directory string ❌ \"\" Subdirectory within the repository containing proto files root string ❌ \"\" Root path used for import resolution"},{"id":"cli/generator/generator::remote-git-repository-input::26","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **URL Format Options:**","content":"Remote Git Repository Input **URL Format Options:**"},{"id":"cli/generator/generator::remote-git-repository-input::27","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input EasyP supports multiple URL formats to give you flexibility in how you reference remote repositories. Each format serves different use cases depending on your stability and versioning requirem","content":"Remote Git Repository Input EasyP supports multiple URL formats to give you flexibility in how you reference remote repositories. Each format serves different use cases depending on your stability and versioning requirements:"},{"id":"cli/generator/generator::remote-git-repository-input::28","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Tagged versions** are recommended for production as they provide stable, immutable references **Semantic versions** offer better readability and dependency management **Commit hashes** give ","content":"Remote Git Repository Input **Tagged versions** are recommended for production as they provide stable, immutable references **Semantic versions** offer better readability and dependency management **Commit hashes** give you access to specific commits when tags aren't available **Latest** should only be used in development environments due to unpredictability **Full HTTPS URLs** are useful for private repositories or non-GitHub hosting"},{"id":"cli/generator/generator::remote-git-repository-input::29","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input ```yaml Tag version - Best for production stability url: \"github.com/googleapis/googleapis@common-protos-1_3_1\"","content":"Remote Git Repository Input ```yaml Tag version - Best for production stability url: \"github.com/googleapis/googleapis@common-protos-1_3_1\""},{"id":"cli/generator/generator::remote-git-repository-input::30","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Semantic version - Easier dependency management url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\"","content":"Remote Git Repository Input Semantic version - Easier dependency management url: \"github.com/grpc-ecosystem/grpc-gateway@v2.19.1\""},{"id":"cli/generator/generator::remote-git-repository-input::31","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Commit hash - When you need a specific commit url: \"github.com/company/protos@abc123def456\"","content":"Remote Git Repository Input Commit hash - When you need a specific commit url: \"github.com/company/protos@abc123def456\""},{"id":"cli/generator/generator::remote-git-repository-input::32","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Latest - Development only, not recommended for production url: \"github.com/company/protos\"","content":"Remote Git Repository Input Latest - Development only, not recommended for production url: \"github.com/company/protos\""},{"id":"cli/generator/generator::remote-git-repository-input::33","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input Full HTTPS URL - For private repos or custom Git hosts url: \"https://github.com/company/private-protos.git\" ```","content":"Remote Git Repository Input Full HTTPS URL - For private repos or custom Git hosts url: \"https://github.com/company/private-protos.git\" ```"},{"id":"cli/generator/generator::remote-git-repository-input::34","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input **Examples:**","content":"Remote Git Repository Input **Examples:**"},{"id":"cli/generator/generator::remote-git-repository-input::35","title":"Generator","section":"Remote Git Repository Input","path":"/docs/guide/cli/generator/generator#remote-git-repository-input","headings":["Remote Git Repository Input"],"excerpt":"Remote Git Repository Input These examples demonstrate common patterns for consuming remote proto definitions from different types of repositories:","content":"Remote Git Repository Input These examples demonstrate common patterns for consuming remote proto definitions from different types of repositories:"},{"id":"cli/generator/generator::plugin-configuration::36","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration Plugin configuration is where you specify which code generators to run and how they should behave. EasyP supports any protoc plugin, making it extremely flexible for different language ecosystems and","content":"Plugin Configuration Plugin configuration is where you specify which code generators to run and how they should behave. EasyP supports any protoc plugin, making it extremely flexible for different language ecosystems and use cases."},{"id":"cli/generator/generator::plugin-configuration::37","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration At a high level, there are **four ways to specify how a plugin should be executed**:","content":"Plugin Configuration At a high level, there are **four ways to specify how a plugin should be executed**:"},{"id":"cli/generator/generator::plugin-configuration::38","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration **name** – run plugin by name from PATH or use a builtin plugin. **path** – run plugin by absolute/relative path to an executable file. **remote** – run plugin via remote URL (EasyP remote executor).","content":"Plugin Configuration **name** – run plugin by name from PATH or use a builtin plugin. **path** – run plugin by absolute/relative path to an executable file. **remote** – run plugin via remote URL (EasyP remote executor). **command** – run plugin via arbitrary command (for example, go run ...)."},{"id":"cli/generator/generator::plugin-configuration::39","title":"Generator","section":"Plugin Configuration","path":"/docs/guide/cli/generator/generator#plugin-configuration","headings":["Plugin Configuration"],"excerpt":"Plugin Configuration Only **one** of name, path, remote, or command must be specified for each plugin.","content":"Plugin Configuration Only **one** of name, path, remote, or command must be specified for each plugin."},{"id":"cli/generator/generator::plugin-by-name-name::40","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) Local plugin execution by name is the standard approach where plugins are installed on your system and executed directly by EasyP.","content":"Plugin by Name (name) Local plugin execution by name is the standard approach where plugins are installed on your system and executed directly by EasyP."},{"id":"cli/generator/generator::plugin-by-name-name::41","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) **When to use name:** Standard language support (Go, Python, TypeScript, etc.) You have control over the build environment Performance is critical (no network overhead) You want to rely on PATH or b","content":"Plugin by Name (name) **When to use name:** Standard language support (Go, Python, TypeScript, etc.) You have control over the build environment Performance is critical (no network overhead) You want to rely on PATH or builtin plugins"},{"id":"cli/generator/generator::plugin-by-name-name::42","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) **Installation requirements:** Plugins must be installed and available in your PATH (if not using builtin plugins). Plugin names follow the protoc-gen-{name} convention. Use package managers (go ins","content":"Plugin by Name (name) **Installation requirements:** Plugins must be installed and available in your PATH (if not using builtin plugins). Plugin names follow the protoc-gen-{name} convention. Use package managers (go install, npm install, pip install) for installation."},{"id":"cli/generator/generator::plugin-by-name-name::43","title":"Generator","section":"Plugin by Name (name)","path":"/docs/guide/cli/generator/generator#plugin-by-name-name","headings":["Plugin by Name (name)"],"excerpt":"Plugin by Name (name) The with_imports parameter is crucial when you're using dependencies from the package manager. Set it to true to include proto files from your deps section in the generation process.","content":"Plugin by Name (name) The with_imports parameter is crucial when you're using dependencies from the package manager. Set it to true to include proto files from your deps section in the generation process."},{"id":"cli/generator/generator::plugin-by-path-path::44","title":"Generator","section":"Plugin by Path (path)","path":"/docs/guide/cli/generator/generator#plugin-by-path-path","headings":["Plugin by Path (path)"],"excerpt":"Plugin by Path (path) Sometimes you need to run a plugin from a specific binary without putting it into PATH (for example, a binary in your repo or in a build directory). In this case you can specify an explicit path:","content":"Plugin by Path (path) Sometimes you need to run a plugin from a specific binary without putting it into PATH (for example, a binary in your repo or in a build directory). In this case you can specify an explicit path:"},{"id":"cli/generator/generator::plugin-by-path-path::45","title":"Generator","section":"Plugin by Path (path)","path":"/docs/guide/cli/generator/generator#plugin-by-path-path","headings":["Plugin by Path (path)"],"excerpt":"Plugin by Path (path) **When to use path:** You keep plugin binaries in the repository (for reproducible builds). You use different plugin versions side-by-side. You don't want to pollute the global PATH.","content":"Plugin by Path (path) **When to use path:** You keep plugin binaries in the repository (for reproducible builds). You use different plugin versions side-by-side. You don't want to pollute the global PATH."},{"id":"cli/generator/generator::remote-plugin-remote::46","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) Remote plugins are executed via a remote URL. EasyP will send a CodeGeneratorRequest to the remote endpoint and receive a CodeGeneratorResponse back.","content":"Remote Plugin (remote) Remote plugins are executed via a remote URL. EasyP will send a CodeGeneratorRequest to the remote endpoint and receive a CodeGeneratorResponse back."},{"id":"cli/generator/generator::remote-plugin-remote::47","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) Below is a real example of using the EasyP API Service as a remote plugin executor (same format as in the API Service docs):","content":"Remote Plugin (remote) Below is a real example of using the EasyP API Service as a remote plugin executor (same format as in the API Service docs):"},{"id":"cli/generator/generator::remote-plugin-remote::48","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) ```yaml generate: plugins: # Remote plugin execution via EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative","content":"Remote Plugin (remote) ```yaml generate: plugins: # Remote plugin execution via EasyP API Service - remote: api.easyp.tech/protobuf/go:v1.36.10 out: . opts: paths: source_relative"},{"id":"cli/generator/generator::remote-plugin-remote::49","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```","content":"Remote Plugin (remote) remote: api.easyp.tech/grpc/go:v1.5.1 out: . opts: paths: source_relative ```"},{"id":"cli/generator/generator::remote-plugin-remote::50","title":"Generator","section":"Remote Plugin (remote)","path":"/docs/guide/cli/generator/generator#remote-plugin-remote","headings":["Remote Plugin (remote)"],"excerpt":"Remote Plugin (remote) **Typical use cases for remote:** Centralized plugin service inside your organization (e.g. EasyP API Service). Running heavy plugins on a dedicated server instead of CI agents. Sharing the same pl","content":"Remote Plugin (remote) **Typical use cases for remote:** Centralized plugin service inside your organization (e.g. EasyP API Service). Running heavy plugins on a dedicated server instead of CI agents. Sharing the same plugin implementation across multiple teams."},{"id":"cli/generator/generator::executing-plugin-via-command-command::51","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) You can specify a plugin as an array of commands to execute. This is useful for running plugins via go run or any other tool without prior installation of the plugin binary:","content":"Executing Plugin via Command (command) You can specify a plugin as an array of commands to execute. This is useful for running plugins via go run or any other tool without prior installation of the plugin binary:"},{"id":"cli/generator/generator::executing-plugin-via-command-command::52","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command)","content":"Executing Plugin via Command (command)"},{"id":"cli/generator/generator::executing-plugin-via-command-command::53","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) In this mode EasyP: **builds and runs the command** you provide as a child process; **writes CodeGeneratorRequest to stdin** of the process; **reads CodeGeneratorResponse from stdou","content":"Executing Plugin via Command (command) In this mode EasyP: **builds and runs the command** you provide as a child process; **writes CodeGeneratorRequest to stdin** of the process; **reads CodeGeneratorResponse from stdout**, just like with regular protoc plugins."},{"id":"cli/generator/generator::executing-plugin-via-command-command::54","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Plugin Source Priority:** command — execute via specified command (highest priority) remote — remote plugin via URL name — local plugin from PATH or builtin plugin path — path to ","content":"Executing Plugin via Command (command) **Plugin Source Priority:** command — execute via specified command (highest priority) remote — remote plugin via URL name — local plugin from PATH or builtin plugin path — path to plugin executable file"},{"id":"cli/generator/generator::executing-plugin-via-command-command::55","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Parameters (plugin sources and common options):**","content":"Executing Plugin via Command (command) **Parameters (plugin sources and common options):**"},{"id":"cli/generator/generator::executing-plugin-via-command-command::56","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- name string ❌ - Plugin name or identifier (e.g. go, go-grpc, grpc-gateway) command ","content":"Executing Plugin via Command (command) Parameter Type Required Default Description ----------- ------ ---------- --------- ------------- name string ❌ - Plugin name or identifier (e.g. go, go-grpc, grpc-gateway) command []string ❌ - Command to execute plugin (e.g., [\"go\", \"run\", \"package\"]) remote string ❌ - Remote plugin URL path string ❌ - Path to plugin executable file out string ❌ resolved generate root Output directory for generated files opts mapstring ❌ {} Plugin-specific options; list values are emitted as repeated key=value params with_imports bool ❌ false Include proto files from dependencies"},{"id":"cli/generator/generator::executing-plugin-via-command-command::57","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Note:** Only one plugin source (name, command, remote, or path) must be specified for each plugin. If opts.outputServices is set to [\"grpc-js\", \"generic-definitions\"], EasyP sends","content":"Executing Plugin via Command (command) **Note:** Only one plugin source (name, command, remote, or path) must be specified for each plugin. If opts.outputServices is set to [\"grpc-js\", \"generic-definitions\"], EasyP sends outputServices=grpc-js,outputServices=generic-definitions."},{"id":"cli/generator/generator::executing-plugin-via-command-command::58","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) **Command source examples:**","content":"Executing Plugin via Command (command) **Command source examples:**"},{"id":"cli/generator/generator::executing-plugin-via-command-command::59","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) ```yaml generate: inputs: - directory: \"proto\"","content":"Executing Plugin via Command (command) ```yaml generate: inputs: - directory: \"proto\""},{"id":"cli/generator/generator::executing-plugin-via-command-command::60","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) plugins: # 1) gRPC-Gateway via go run (no pre-installed binary required) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.25.1\"] out: .","content":"Executing Plugin via Command (command) plugins: # 1) gRPC-Gateway via go run (no pre-installed binary required) - command: [\"go\", \"run\", \"github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.25.1\"] out: ./gen/go opts: paths: source_relative generate_unbound_methods: true"},{"id":"cli/generator/generator::executing-plugin-via-command-command::61","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) 2) protoc-gen-validate via go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go","content":"Executing Plugin via Command (command) 2) protoc-gen-validate via go run - command: [\"go\", \"run\", \"github.com/bufbuild/protoc-gen-validate@v0.10.1\"] out: ./gen/go opts: paths: source_relative lang: go"},{"id":"cli/generator/generator::executing-plugin-via-command-command::62","title":"Generator","section":"Executing Plugin via Command (command)","path":"/docs/guide/cli/generator/generator#executing-plugin-via-command-command","headings":["Executing Plugin via Command (command)"],"excerpt":"Executing Plugin via Command (command) 3) Any custom wrapper script - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```","content":"Executing Plugin via Command (command) 3) Any custom wrapper script - command: [\"bash\", \"./scripts/custom-protoc-plugin.sh\"] out: ./gen/custom opts: foo: bar ```"},{"id":"cli/generator/generator::builtin-plugins::63","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins EasyP includes builtin plugins for basic protobuf and gRPC languages. These plugins are embedded in the binary as WASM modules and do not require installation of external dependencies.","content":"Builtin Plugins EasyP includes builtin plugins for basic protobuf and gRPC languages. These plugins are embedded in the binary as WASM modules and do not require installation of external dependencies."},{"id":"cli/generator/generator::builtin-plugins::64","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins **Benefits of builtin plugins:** **Portability**: Single binary with all necessary plugins **Convenience**: No need to install external dependencies **Stability**: Plugin versions are fixed in the binary ","content":"Builtin Plugins **Benefits of builtin plugins:** **Portability**: Single binary with all necessary plugins **Convenience**: No need to install external dependencies **Stability**: Plugin versions are fixed in the binary **Isolation**: Independent of system plugin installations"},{"id":"cli/generator/generator::builtin-plugins::65","title":"Generator","section":"Builtin Plugins","path":"/docs/guide/cli/generator/generator#builtin-plugins","headings":["Builtin Plugins"],"excerpt":"Builtin Plugins **Supported builtin plugins:**","content":"Builtin Plugins **Supported builtin plugins:**"},{"id":"cli/generator/generator::protobuf-base-plugins::66","title":"Generator","section":"Protobuf Base Plugins","path":"/docs/guide/cli/generator/generator#protobuf-base-plugins","headings":["Protobuf Base Plugins"],"excerpt":"Protobuf Base Plugins The following plugins are builtin for generating base protobuf code:","content":"Protobuf Base Plugins The following plugins are builtin for generating base protobuf code:"},{"id":"cli/generator/generator::protobuf-base-plugins::67","title":"Generator","section":"Protobuf Base Plugins","path":"/docs/guide/cli/generator/generator#protobuf-base-plugins","headings":["Protobuf Base Plugins"],"excerpt":"Protobuf Base Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- cpp Generate C++ code from proto files protoc-gen-cpp csharp Generate C# code from proto ","content":"Protobuf Base Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- cpp Generate C++ code from proto files protoc-gen-cpp csharp Generate C# code from proto files protoc-gen-csharp java Generate Java code from proto files protoc-gen-java kotlin Generate Kotlin code from proto files protoc-gen-kotlin objc Generate Objective-C code from proto files protoc-gen-objc php Generate PHP code from proto files protoc-gen-php python Generate Python code from proto files protoc-gen-python ruby Generate Ruby code from proto files protoc-gen-ruby"},{"id":"cli/generator/generator::grpc-plugins::68","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins The following plugins are builtin for generating gRPC code:","content":"gRPC Plugins The following plugins are builtin for generating gRPC code:"},{"id":"cli/generator/generator::grpc-plugins::69","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- grpc_cpp Generate gRPC code for C++ grpc_cpp_plugin grpc_csharp Generate gRPC code for C# grpc_csh","content":"gRPC Plugins Plugin Name Description Corresponding protoc Plugin ------------- ------------- ---------------------------- grpc_cpp Generate gRPC code for C++ grpc_cpp_plugin grpc_csharp Generate gRPC code for C# grpc_csharp_plugin grpc_java Generate gRPC code for Java grpc_java_plugin grpc_node Generate gRPC code for Node.js grpc_node_plugin grpc_objc Generate gRPC code for Objective-C grpc_objective_c_plugin grpc_php Generate gRPC code for PHP grpc_php_plugin grpc_python Generate gRPC code for Python grpc_python_plugin grpc_ruby Generate gRPC code for Ruby grpc_ruby_plugin"},{"id":"cli/generator/generator::grpc-plugins::70","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Plugin Selection Logic:**","content":"gRPC Plugins **Plugin Selection Logic:**"},{"id":"cli/generator/generator::grpc-plugins::71","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins EasyP uses the following priority when selecting an executor for a plugin:","content":"gRPC Plugins EasyP uses the following priority when selecting an executor for a plugin:"},{"id":"cli/generator/generator::grpc-plugins::72","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Remote plugin** (if url is specified) — always has the highest priority **Builtin plugin** (if plugin is builtin and not found in PATH) — used automatically **Local plugin** (from PATH) — used by default f","content":"gRPC Plugins **Remote plugin** (if url is specified) — always has the highest priority **Builtin plugin** (if plugin is builtin and not found in PATH) — used automatically **Local plugin** (from PATH) — used by default for backward compatibility"},{"id":"cli/generator/generator::grpc-plugins::73","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Usage Example:**","content":"gRPC Plugins **Usage Example:**"},{"id":"cli/generator/generator::grpc-plugins::74","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Requirements:**","content":"gRPC Plugins **Requirements:**"},{"id":"cli/generator/generator::grpc-plugins::75","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Builtin plugins are included in the EasyP binary:","content":"gRPC Plugins Builtin plugins are included in the EasyP binary:"},{"id":"cli/generator/generator::grpc-plugins::76","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins ```bash Build go build ./cmd/easyp","content":"gRPC Plugins ```bash Build go build ./cmd/easyp"},{"id":"cli/generator/generator::grpc-plugins::77","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Install go install github.com/easyp-tech/easyp/cmd/easyp@latest ```","content":"gRPC Plugins Install go install github.com/easyp-tech/easyp/cmd/easyp@latest ```"},{"id":"cli/generator/generator::grpc-plugins::78","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins **Backward Compatibility:**","content":"gRPC Plugins **Backward Compatibility:**"},{"id":"cli/generator/generator::grpc-plugins::79","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Builtin plugins are fully compatible with existing configurations. If a plugin is found in PATH, it will be used instead of the builtin one. This ensures that:","content":"gRPC Plugins Builtin plugins are fully compatible with existing configurations. If a plugin is found in PATH, it will be used instead of the builtin one. This ensures that:"},{"id":"cli/generator/generator::grpc-plugins::80","title":"Generator","section":"gRPC Plugins","path":"/docs/guide/cli/generator/generator#grpc-plugins","headings":["gRPC Plugins"],"excerpt":"gRPC Plugins Existing configurations continue to work without changes You can override a builtin plugin by installing it in your system Priority is given to local installations for flexibility","content":"gRPC Plugins Existing configurations continue to work without changes You can override a builtin plugin by installing it in your system Priority is given to local installations for flexibility"},{"id":"cli/generator/generator::plugin-options-reference::81","title":"Generator","section":"Plugin Options Reference","path":"/docs/guide/cli/generator/generator#plugin-options-reference","headings":["Plugin Options Reference"],"excerpt":"Plugin Options Reference This section covers the most commonly used plugins and their configuration options. Each plugin has specific parameters that control how code is generated, and understanding these options is cruc","content":"Plugin Options Reference This section covers the most commonly used plugins and their configuration options. Each plugin has specific parameters that control how code is generated, and understanding these options is crucial for getting the output you need."},{"id":"cli/generator/generator::go-plugins::82","title":"Generator","section":"Go Plugins","path":"/docs/guide/cli/generator/generator#go-plugins","headings":["Go Plugins"],"excerpt":"Go Plugins Go plugins are the most mature and widely used protoc plugins. The paths option controls how import paths are resolved, while other options provide fine-grained control over the generated code:","content":"Go Plugins Go plugins are the most mature and widely used protoc plugins. The paths option controls how import paths are resolved, while other options provide fine-grained control over the generated code:"},{"id":"cli/generator/generator::grpc-gateway-plugins::83","title":"Generator","section":"gRPC-Gateway Plugins","path":"/docs/guide/cli/generator/generator#grpc-gateway-plugins","headings":["gRPC-Gateway Plugins"],"excerpt":"gRPC-Gateway Plugins gRPC-Gateway plugins enable you to serve gRPC services as REST APIs and generate OpenAPI documentation. These are essential for building HTTP/JSON APIs from gRPC services:","content":"gRPC-Gateway Plugins gRPC-Gateway plugins enable you to serve gRPC services as REST APIs and generate OpenAPI documentation. These are essential for building HTTP/JSON APIs from gRPC services:"},{"id":"cli/generator/generator::validation-plugins::84","title":"Generator","section":"Validation Plugins","path":"/docs/guide/cli/generator/generator#validation-plugins","headings":["Validation Plugins"],"excerpt":"Validation Plugins Validation plugins generate code that automatically validates proto message fields based on constraints defined in your proto files. This eliminates the need for manual validation code:","content":"Validation Plugins Validation plugins generate code that automatically validates proto message fields based on constraints defined in your proto files. This eliminates the need for manual validation code:"},{"id":"cli/generator/generator::typescriptjavascript-plugins::85","title":"Generator","section":"TypeScript/JavaScript Plugins","path":"/docs/guide/cli/generator/generator#typescriptjavascript-plugins","headings":["TypeScript/JavaScript Plugins"],"excerpt":"TypeScript/JavaScript Plugins TypeScript plugins are essential for frontend development, providing type-safe interfaces for your proto definitions and gRPC services in web applications:","content":"TypeScript/JavaScript Plugins TypeScript plugins are essential for frontend development, providing type-safe interfaces for your proto definitions and gRPC services in web applications:"},{"id":"cli/generator/generator::managed-mode::86","title":"Generator","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode Managed mode automatically sets file and field options in your protobuf descriptors during code generation without modifying the original .proto files. This feature is compatible with buf's managed mode and ","content":"Managed Mode Managed mode automatically sets file and field options in your protobuf descriptors during code generation without modifying the original .proto files. This feature is compatible with buf's managed mode and provides a consistent way to manage language-specific options across your codebase."},{"id":"cli/generator/generator::managed-mode::87","title":"Generator","section":"Managed Mode","path":"/docs/guide/cli/generator/generator#managed-mode","headings":["Managed Mode"],"excerpt":"Managed Mode **Key benefits:** **No proto file modifications**: Options are applied at generation time, keeping your proto files clean **Consistent defaults**: Automatic application of language-specific naming convention","content":"Managed Mode **Key benefits:** **No proto file modifications**: Options are applied at generation time, keeping your proto files clean **Consistent defaults**: Automatic application of language-specific naming conventions **Centralized configuration**: Manage all options in one place (easyp.yaml) **Module-specific rules**: Apply different options to different modules or paths **buf compatibility**: Works the same way as buf managed mode"},{"id":"cli/generator/generator::how-it-works::88","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works When managed mode is enabled, EasyP automatically applies file and field options to your protobuf descriptors before code generation. This happens in memory, so your original .proto files remain unchanged.","content":"How It Works When managed mode is enabled, EasyP automatically applies file and field options to your protobuf descriptors before code generation. This happens in memory, so your original .proto files remain unchanged."},{"id":"cli/generator/generator::how-it-works::89","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Default values** are applied for certain options based on language conventions: Java: java_package_prefix defaults to \"com\", java_multiple_files defaults to true C#: csharp_namespace defaults to PascalCase","content":"How It Works **Default values** are applied for certain options based on language conventions: Java: java_package_prefix defaults to \"com\", java_multiple_files defaults to true C#: csharp_namespace defaults to PascalCase of package name Ruby: ruby_package defaults to PascalCase with :: separator PHP: php_namespace defaults to PascalCase with \\ separator Objective-C: objc_class_prefix defaults to first letters of package parts C++: cc_enable_arenas defaults to true"},{"id":"cli/generator/generator::how-it-works::90","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, protobuf package, path, or field. Without module, package, or path, an override applies to all files in the g","content":"How It Works **Overrides** allow you to set specific values for options, with support for filtering by module, protobuf package, path, or field. Without module, package, or path, an override applies to all files in the generation request, including dependencies and git_repo inputs."},{"id":"cli/generator/generator::how-it-works::91","title":"Generator","section":"How It Works","path":"/docs/guide/cli/generator/generator#how-it-works","headings":["How It Works"],"excerpt":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files. This is the recommended way to exclude external dependencies that already define their own options.","content":"How It Works **Disables** allow you to prevent managed mode from modifying specific options or files. This is the recommended way to exclude external dependencies that already define their own options."},{"id":"cli/generator/generator::configuration::92","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration ```yaml generate: managed: enabled: true disable: # Disable managed mode for specific module - module: github.com/googleapis/googleapis # Disable specific option globally - file_option: java_package_prefix","content":"Configuration ```yaml generate: managed: enabled: true disable: # Disable managed mode for specific module - module: github.com/googleapis/googleapis # Disable specific option globally - file_option: java_package_prefix"},{"id":"cli/generator/generator::configuration::93","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration Disable for specific protobuf package - package: acme.weather.v1 file_option: java_package # Disable for specific path - path: legacy/ file_option: go_package # Disable field option for specific field - fie","content":"Configuration Disable for specific protobuf package - package: acme.weather.v1 file_option: java_package # Disable for specific path - path: legacy/ file_option: go_package # Disable field option for specific field - field_option: jstype field: com.example.User.id override: # Override go_package_prefix for all files - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go # Override for specific module - file_option: java_package_prefix value: com.mycompany module: github.com/mycompany/internal-protos"},{"id":"cli/generator/generator::configuration::94","title":"Generator","section":"Configuration","path":"/docs/guide/cli/generator/generator#configuration","headings":["Configuration"],"excerpt":"Configuration Override for specific protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Override for specific path - file_option: csharp_namespace_pre","content":"Configuration Override for specific protobuf package - file_option: go_package_prefix value: github.com/mycompany/myproject/gen/go package: acme.weather.v1 # Override for specific path - file_option: csharp_namespace_prefix value: MyCompany path: api/v1/ # Override for multiple files with same value using prefix path # This matches both internal/cms/bmi.proto and internal/cms/bmi_service.proto - file_option: go_package value: spec/cms/bmi path: \"internal/cms/bmi\" # Override field option for specific path - field_option: jstype value: JS_STRING path: api/v1/ # Override for specific field - field_option: jstype value: JS_NUMBER field: com.example.User.big_id ```"},{"id":"cli/generator/generator::supported-file-options::95","title":"Generator","section":"Supported File Options","path":"/docs/guide/cli/generator/generator#supported-file-options","headings":["Supported File Options"],"excerpt":"Supported File Options Option Description Has Default? -------- ------------- -------------- go_package Go import path ❌ go_package_prefix Prefix for Go import paths ❌ java_package Java package name ❌ java_package_prefix","content":"Supported File Options Option Description Has Default? -------- ------------- -------------- go_package Go import path ❌ go_package_prefix Prefix for Go import paths ❌ java_package Java package name ❌ java_package_prefix Prefix for Java packages ✅ (\"com\") java_package_suffix Suffix for Java packages ❌ java_multiple_files Generate multiple Java files ✅ (true) java_outer_classname Outer class name ✅ (PascalCase + \"Proto\") java_string_check_utf8 UTF-8 validation ❌ csharp_namespace C# namespace ✅ (PascalCase) csharp_namespace_prefix Prefix for C# namespaces ❌ ruby_package Ruby module name ✅ (PascalCase with ::) ruby_package_suffix Suffix for Ruby packages ❌ php_namespace PHP namespace ✅ (PascalCase with \\) php_metadata_namespace PHP metadata namespace ❌ php_metadata_namespace_suffix Suffix for PHP metadata ❌ objc_class_prefix Objective-C class prefix ✅ (First letters) swift_prefix Swift prefix ❌ optimize_for Code generation optimization ❌ cc_enable_arenas C++ arena allocation ✅ (true)"},{"id":"cli/generator/generator::supported-field-options::96","title":"Generator","section":"Supported Field Options","path":"/docs/guide/cli/generator/generator#supported-field-options","headings":["Supported Field Options"],"excerpt":"Supported Field Options Option Description Applies To -------- ------------- ------------ jstype JavaScript type for 64-bit integers int64, uint64, sint64, fixed64, sfixed64","content":"Supported Field Options Option Description Applies To -------- ------------- ------------ jstype JavaScript type for 64-bit integers int64, uint64, sint64, fixed64, sfixed64"},{"id":"cli/generator/generator::basic-setup-with-defaults::97","title":"Generator","section":"Basic Setup with Defaults","path":"/docs/guide/cli/generator/generator#basic-setup-with-defaults","headings":["Basic Setup with Defaults"],"excerpt":"Basic Setup with Defaults Enable managed mode to get automatic defaults for all supported languages:","content":"Basic Setup with Defaults Enable managed mode to get automatic defaults for all supported languages:"},{"id":"cli/generator/generator::basic-setup-with-defaults::98","title":"Generator","section":"Basic Setup with Defaults","path":"/docs/guide/cli/generator/generator#basic-setup-with-defaults","headings":["Basic Setup with Defaults"],"excerpt":"Basic Setup with Defaults This will automatically: Set java_package to com. for all files Set java_multiple_files to true Set csharp_namespace to PascalCase of package name Set ruby_package to PascalCase with :: separato","content":"Basic Setup with Defaults This will automatically: Set java_package to com. for all files Set java_multiple_files to true Set csharp_namespace to PascalCase of package name Set ruby_package to PascalCase with :: separator And more..."},{"id":"cli/generator/generator::custom-go-package-prefix::99","title":"Generator","section":"Custom Go Package Prefix","path":"/docs/guide/cli/generator/generator#custom-go-package-prefix","headings":["Custom Go Package Prefix"],"excerpt":"Custom Go Package Prefix Override the Go package prefix for your project:","content":"Custom Go Package Prefix Override the Go package prefix for your project:"},{"id":"cli/generator/generator::custom-go-package-prefix::100","title":"Generator","section":"Custom Go Package Prefix","path":"/docs/guide/cli/generator/generator#custom-go-package-prefix","headings":["Custom Go Package Prefix"],"excerpt":"Custom Go Package Prefix This will set go_package to github.com/mycompany/myproject/gen/go/ for all files.","content":"Custom Go Package Prefix This will set go_package to github.com/mycompany/myproject/gen/go/ for all files."},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::101","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers For more complex path generation, you can use markers in go_package_prefix or go_package values:","content":"Dynamic Go Package Paths with Markers For more complex path generation, you can use markers in go_package_prefix or go_package values:"},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::102","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers","content":"Dynamic Go Package Paths with Markers"},{"id":"cli/generator/generator::dynamic-go-package-paths-with-markers::103","title":"Generator","section":"Dynamic Go Package Paths with Markers","path":"/docs/guide/cli/generator/generator#dynamic-go-package-paths-with-markers","headings":["Dynamic Go Package Paths with Markers"],"excerpt":"Dynamic Go Package Paths with Markers **Available markers:** {{file_path}} - Full file path without .proto extension - Example: internal/cms/as.proto → internal/cms/as {{file_dir}} - Directory path only, without filename","content":"Dynamic Go Package Paths with Markers **Available markers:** {{file_path}} - Full file path without .proto extension - Example: internal/cms/as.proto → internal/cms/as {{file_dir}} - Directory path only, without filename - Example: internal/cms/as.proto → internal/cms {{file_dir_without:prefix/}} - Directory path with prefix removed, and base filename without _service/_grpc suffixes - Example: {{file_dir_without:internal/}} for internal/cms/as_service.proto → cms/as {{file_path_without:prefix/}} - Full file path with prefix removed - Example: {{file_path_without:internal/}} for internal/cms/as.proto → cms/as"},{"id":"cli/generator/generator::module-specific-overrides::104","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides Apply different options to different modules:","content":"Module-Specific Overrides Apply different options to different modules:"},{"id":"cli/generator/generator::module-specific-overrides::105","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides module matches the EasyP module source exactly: the dependency or git_repo.url value before @version (for example github.com/mycompany/internal-protos or https://github.com/mycompany/internal-pr","content":"Module-Specific Overrides module matches the EasyP module source exactly: the dependency or git_repo.url value before @version (for example github.com/mycompany/internal-protos or https://github.com/mycompany/internal-protos). It is not the Go module path from go.mod."},{"id":"cli/generator/generator::module-specific-overrides::106","title":"Generator","section":"Module-Specific Overrides","path":"/docs/guide/cli/generator/generator#module-specific-overrides","headings":["Module-Specific Overrides"],"excerpt":"Module-Specific Overrides package matches the protobuf package declaration exactly, for example acme.weather.v1.","content":"Module-Specific Overrides package matches the protobuf package declaration exactly, for example acme.weather.v1."},{"id":"cli/generator/generator::package-specific-overrides::107","title":"Generator","section":"Package-Specific Overrides","path":"/docs/guide/cli/generator/generator#package-specific-overrides","headings":["Package-Specific Overrides"],"excerpt":"Package-Specific Overrides Apply different options to files from a specific protobuf package:","content":"Package-Specific Overrides Apply different options to files from a specific protobuf package:"},{"id":"cli/generator/generator::disabling-for-external-dependencies::108","title":"Generator","section":"Disabling for External Dependencies","path":"/docs/guide/cli/generator/generator#disabling-for-external-dependencies","headings":["Disabling for External Dependencies"],"excerpt":"Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set:","content":"Disabling for External Dependencies Disable managed mode for external dependencies that already have their options set:"},{"id":"cli/generator/generator::disabling-for-external-dependencies::109","title":"Generator","section":"Disabling for External Dependencies","path":"/docs/guide/cli/generator/generator#disabling-for-external-dependencies","headings":["Disabling for External Dependencies"],"excerpt":"Disabling for External Dependencies","content":"Disabling for External Dependencies"},{"id":"cli/generator/generator::javascript-type-safety::110","title":"Generator","section":"JavaScript Type Safety","path":"/docs/guide/cli/generator/generator#javascript-type-safety","headings":["JavaScript Type Safety"],"excerpt":"JavaScript Type Safety Set jstype to JS_STRING for all 64-bit integer fields to prevent precision loss in JavaScript:","content":"JavaScript Type Safety Set jstype to JS_STRING for all 64-bit integer fields to prevent precision loss in JavaScript:"},{"id":"cli/generator/generator::path-matching::111","title":"Generator","section":"Path Matching","path":"/docs/guide/cli/generator/generator#path-matching","headings":["Path Matching"],"excerpt":"Path Matching Path matching in managed mode uses prefix-based matching (same as buf):","content":"Path Matching Path matching in managed mode uses prefix-based matching (same as buf):"},{"id":"cli/generator/generator::path-matching::112","title":"Generator","section":"Path Matching","path":"/docs/guide/cli/generator/generator#path-matching","headings":["Path Matching"],"excerpt":"Path Matching **Directory path** (ending with /): Matches all files in that directory and subdirectories - Example: path: \"internal/cms/\" matches internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.pr","content":"Path Matching **Directory path** (ending with /): Matches all files in that directory and subdirectories - Example: path: \"internal/cms/\" matches internal/cms/as.proto, internal/cms/node.proto, internal/cms/v1/service.proto **Exact file path** (ending with .proto): Matches only that specific file - Example: path: \"internal/cms/as.proto\" matches only internal/cms/as.proto **Prefix path** (no trailing / or .proto): Uses prefix matching (not directory-aware) - Example: path: \"internal/cms\" matches internal/cms/as.proto but also internal/cmsv2/file.proto"},{"id":"cli/generator/generator::rule-precedence::113","title":"Generator","section":"Rule Precedence","path":"/docs/guide/cli/generator/generator#rule-precedence","headings":["Rule Precedence"],"excerpt":"Rule Precedence When multiple rules match the same file or field, the following precedence applies:","content":"Rule Precedence When multiple rules match the same file or field, the following precedence applies:"},{"id":"cli/generator/generator::rule-precedence::114","title":"Generator","section":"Rule Precedence","path":"/docs/guide/cli/generator/generator#rule-precedence","headings":["Rule Precedence"],"excerpt":"Rule Precedence **Disable rules** take precedence - if an option is disabled, it won't be applied **Override rules** are applied in order - the last matching rule wins **Default values** are applied only if no override m","content":"Rule Precedence **Disable rules** take precedence - if an option is disabled, it won't be applied **Override rules** are applied in order - the last matching rule wins **Default values** are applied only if no override matches and the option isn't disabled"},{"id":"cli/generator/generator::compatibility-with-buf::115","title":"Generator","section":"Compatibility with buf","path":"/docs/guide/cli/generator/generator#compatibility-with-buf","headings":["Compatibility with buf"],"excerpt":"Compatibility with buf EasyP's managed mode is compatible with buf's managed mode. The same configuration format and behavior apply, making it easy to migrate between tools or use both in the same workflow.","content":"Compatibility with buf EasyP's managed mode is compatible with buf's managed mode. The same configuration format and behavior apply, making it easy to migrate between tools or use both in the same workflow."},{"id":"cli/generator/generator::descriptor-set-generation::116","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **https://protobuf.dev/programming-guides/techniques/#self-description**","content":"Descriptor Set Generation **https://protobuf.dev/programming-guides/techniques/#self-description**"},{"id":"cli/generator/generator::descriptor-set-generation::117","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation EasyP supports generating binary FileDescriptorSet files using the --descriptor_set_out flag. This allows you to create self-describing protobuf messages that include schema information alongsid","content":"Descriptor Set Generation EasyP supports generating binary FileDescriptorSet files using the --descriptor_set_out flag. This allows you to create self-describing protobuf messages that include schema information alongside the data."},{"id":"cli/generator/generator::descriptor-set-generation::118","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **CLI flags:**","content":"Descriptor Set Generation **CLI flags:**"},{"id":"cli/generator/generator::descriptor-set-generation::119","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation --descriptor_set_out - Output path for the binary FileDescriptorSet --include_imports - Include all transitive dependencies in the FileDescriptorSet","content":"Descriptor Set Generation --descriptor_set_out - Output path for the binary FileDescriptorSet --include_imports - Include all transitive dependencies in the FileDescriptorSet"},{"id":"cli/generator/generator::descriptor-set-generation::120","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation **Example:**","content":"Descriptor Set Generation **Example:**"},{"id":"cli/generator/generator::descriptor-set-generation::121","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation ```bash Generate descriptor set with only target files easyp generate --descriptor_set_out=./schema.pb","content":"Descriptor Set Generation ```bash Generate descriptor set with only target files easyp generate --descriptor_set_out=./schema.pb"},{"id":"cli/generator/generator::descriptor-set-generation::122","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation Generate descriptor set with all dependencies easyp generate --descriptor_set_out=./schema.pb --include_imports ```","content":"Descriptor Set Generation Generate descriptor set with all dependencies easyp generate --descriptor_set_out=./schema.pb --include_imports ```"},{"id":"cli/generator/generator::descriptor-set-generation::123","title":"Generator","section":"Descriptor Set Generation","path":"/docs/guide/cli/generator/generator#descriptor-set-generation","headings":["Descriptor Set Generation"],"excerpt":"Descriptor Set Generation Self-describing messages are useful for dynamic message parsing, runtime schema validation, schema registries, and building generic gRPC clients. For more information, see the Protocol Buffers d","content":"Descriptor Set Generation Self-describing messages are useful for dynamic message parsing, runtime schema validation, schema registries, and building generic gRPC clients. For more information, see the Protocol Buffers documentation on self-description."},{"id":"cli/generator/generator::package-manager-integration::124","title":"Generator","section":"Package Manager Integration","path":"/docs/guide/cli/generator/generator#package-manager-integration","headings":["Package Manager Integration"],"excerpt":"Package Manager Integration One of EasyP's most powerful features is the seamless integration between the package manager and code generator. This integration eliminates the common problem of managing proto dependencies ","content":"Package Manager Integration One of EasyP's most powerful features is the seamless integration between the package manager and code generator. This integration eliminates the common problem of managing proto dependencies manually and ensures that your generated code always has access to the correct versions of imported proto files."},{"id":"cli/generator/generator::package-manager-integration::125","title":"Generator","section":"Package Manager Integration","path":"/docs/guide/cli/generator/generator#package-manager-integration","headings":["Package Manager Integration"],"excerpt":"Package Manager Integration **Key benefits:** **Automatic dependency resolution**: No need to manually manage proto import paths **Version consistency**: Dependencies are locked to specific versions via easyp.lock **Tran","content":"Package Manager Integration **Key benefits:** **Automatic dependency resolution**: No need to manually manage proto import paths **Version consistency**: Dependencies are locked to specific versions via easyp.lock **Transitive dependencies**: EasyP handles dependencies of dependencies automatically **Performance**: Local caching means dependencies are downloaded once and reused"},{"id":"cli/generator/generator::automatic-dependency-resolution::126","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution When you define dependencies in the deps section, the generator automatically includes them in the proto path. This means your proto files can import from these dependencies without any ad","content":"Automatic Dependency Resolution When you define dependencies in the deps section, the generator automatically includes them in the proto path. This means your proto files can import from these dependencies without any additional configuration."},{"id":"cli/generator/generator::automatic-dependency-resolution::127","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution **How it works:** EasyP downloads and caches dependencies based on your deps configuration During generation, these cached proto files are automatically added to the protoc import path You","content":"Automatic Dependency Resolution **How it works:** EasyP downloads and caches dependencies based on your deps configuration During generation, these cached proto files are automatically added to the protoc import path Your proto files can import from dependencies using standard import statements Generated code includes both your local protos and dependency protos when with_imports: true"},{"id":"cli/generator/generator::automatic-dependency-resolution::128","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution Here's a simple example showing how dependency resolution works automatically. Notice that you only need to specify the dependencies once in the deps section:","content":"Automatic Dependency Resolution Here's a simple example showing how dependency resolution works automatically. Notice that you only need to specify the dependencies once in the deps section:"},{"id":"cli/generator/generator::automatic-dependency-resolution::129","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1","content":"Automatic Dependency Resolution ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc-ecosystem/grpc-gateway@v2.19.1"},{"id":"cli/generator/generator::automatic-dependency-resolution::130","title":"Generator","section":"Automatic Dependency Resolution","path":"/docs/guide/cli/generator/generator#automatic-dependency-resolution","headings":["Automatic Dependency Resolution"],"excerpt":"Automatic Dependency Resolution generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway protos ``","content":"Automatic Dependency Resolution generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true # This automatically includes googleapis and grpc-gateway protos ```"},{"id":"cli/generator/generator::dependency-usage-examples::131","title":"Generator","section":"Dependency Usage Examples","path":"/docs/guide/cli/generator/generator#dependency-usage-examples","headings":["Dependency Usage Examples"],"excerpt":"Dependency Usage Examples The following examples demonstrate common patterns for integrating external proto dependencies into your code generation workflow.","content":"Dependency Usage Examples The following examples demonstrate common patterns for integrating external proto dependencies into your code generation workflow."},{"id":"cli/generator/generator::using-google-apis::132","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs Google APIs are among the most commonly used proto dependencies, providing standard types and annotations for REST APIs, field validation, and common data structures.","content":"Using Google APIs Google APIs are among the most commonly used proto dependencies, providing standard types and annotations for REST APIs, field validation, and common data structures."},{"id":"cli/generator/generator::using-google-apis::133","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs **When to use Google APIs:** Building REST APIs with gRPC-Gateway Need standard types like Timestamp, Duration, Any Want to use Google's field behavior annotations Building services that integrate with ","content":"Using Google APIs **When to use Google APIs:** Building REST APIs with gRPC-Gateway Need standard types like Timestamp, Duration, Any Want to use Google's field behavior annotations Building services that integrate with Google Cloud"},{"id":"cli/generator/generator::using-google-apis::134","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs This configuration shows the minimal setup needed to use Google APIs in your proto files:","content":"Using Google APIs This configuration shows the minimal setup needed to use Google APIs in your proto files:"},{"id":"cli/generator/generator::using-google-apis::135","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Using Google APIs ```yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/generator/generator::using-google-apis::136","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```","content":"Using Google APIs generate: inputs: - directory: \"api/proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true ```"},{"id":"cli/generator/generator::using-google-apis::137","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs **Important:** Always use a pinned version (like common-protos-1_3_1) rather than latest to ensure build reproducibility.","content":"Using Google APIs **Important:** Always use a pinned version (like common-protos-1_3_1) rather than latest to ensure build reproducibility."},{"id":"cli/generator/generator::using-google-apis::138","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs Once configured, your proto files can import and use Google API definitions. Here's an example of a service using HTTP annotations:","content":"Using Google APIs Once configured, your proto files can import and use Google API definitions. Here's an example of a service using HTTP annotations:"},{"id":"cli/generator/generator::using-google-apis::139","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";","content":"Using Google APIs ```proto // api/proto/service.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::using-google-apis::140","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";","content":"Using Google APIs import \"google/api/annotations.proto\"; import \"google/protobuf/timestamp.proto\";"},{"id":"cli/generator/generator::using-google-apis::141","title":"Generator","section":"Using Google APIs","path":"/docs/guide/cli/generator/generator#using-google-apis","headings":["Using Google APIs"],"excerpt":"Using Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```","content":"Using Google APIs service MyService { rpc GetData(GetDataRequest) returns (GetDataResponse) { option (google.api.http) = { get: \"/v1/data\" }; } } ```"},{"id":"cli/generator/generator::using-validation-rules::142","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules Protoc-gen-validate provides powerful field validation capabilities that can be embedded directly in your proto definitions, eliminating the need for separate validation logic in your application c","content":"Using Validation Rules Protoc-gen-validate provides powerful field validation capabilities that can be embedded directly in your proto definitions, eliminating the need for separate validation logic in your application code."},{"id":"cli/generator/generator::using-validation-rules::143","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **When to use validation:** Input validation for API endpoints Database model constraints Configuration file validation Any scenario where data integrity is critical","content":"Using Validation Rules **When to use validation:** Input validation for API endpoints Database model constraints Configuration file validation Any scenario where data integrity is critical"},{"id":"cli/generator/generator::using-validation-rules::144","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **Benefits:** Validation rules are part of the proto definition (single source of truth) Code generation creates validation functions automatically Consistent validation across different languages ","content":"Using Validation Rules **Benefits:** Validation rules are part of the proto definition (single source of truth) Code generation creates validation functions automatically Consistent validation across different languages Better performance than runtime reflection-based validation"},{"id":"cli/generator/generator::using-validation-rules::145","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1","content":"Using Validation Rules ```yaml deps: - github.com/bufbuild/protoc-gen-validate@v0.10.1"},{"id":"cli/generator/generator::using-validation-rules::146","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true - name: validate-go out: ./gen/go opts: paths: source_relative ```","content":"Using Validation Rules generate: inputs: - directory: \"proto\" plugins: - name: go out: ./gen/go opts: paths: source_relative with_imports: true - name: validate-go out: ./gen/go opts: paths: source_relative ```"},{"id":"cli/generator/generator::using-validation-rules::147","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules **Note:** You need both the dependency (for proto imports) and the plugin (for code generation) to get full validation support.","content":"Using Validation Rules **Note:** You need both the dependency (for proto imports) and the plugin (for code generation) to get full validation support."},{"id":"cli/generator/generator::using-validation-rules::148","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules Here's how validation rules look in your proto files. The generated code will automatically validate these constraints:","content":"Using Validation Rules Here's how validation rules look in your proto files. The generated code will automatically validate these constraints:"},{"id":"cli/generator/generator::using-validation-rules::149","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules ```proto // proto/user.proto syntax = \"proto3\";","content":"Using Validation Rules ```proto // proto/user.proto syntax = \"proto3\";"},{"id":"cli/generator/generator::using-validation-rules::150","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules import \"validate/validate.proto\";","content":"Using Validation Rules import \"validate/validate.proto\";"},{"id":"cli/generator/generator::using-validation-rules::151","title":"Generator","section":"Using Validation Rules","path":"/docs/guide/cli/generator/generator#using-validation-rules","headings":["Using Validation Rules"],"excerpt":"Using Validation Rules message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```","content":"Using Validation Rules message User { string email = 1 [(validate.rules).string.email = true]; int32 age = 2 [(validate.rules).int32.gte = 0]; } ```"},{"id":"cli/generator/generator::complex-multi-dependency-setup::152","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup This example demonstrates a production-ready configuration that combines multiple dependencies and plugins for a complete API development workflow:","content":"Complex Multi-Dependency Setup This example demonstrates a production-ready configuration that combines multiple dependencies and plugins for a complete API development workflow:"},{"id":"cli/generator/generator::complex-multi-dependency-setup::153","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup ```yaml deps: # Core Google APIs - Standard types and HTTP annotations - github.com/googleapis/googleapis@common-protos-1_3_1 # gRPC Gateway for REST APIs - Enables HTTP/JSON interfaces - g","content":"Complex Multi-Dependency Setup ```yaml deps: # Core Google APIs - Standard types and HTTP annotations - github.com/googleapis/googleapis@common-protos-1_3_1 # gRPC Gateway for REST APIs - Enables HTTP/JSON interfaces - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 # Validation rules - Field-level validation constraints - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Company internal shared types - Common business objects - github.com/mycompany/shared-protos@v1.5.0"},{"id":"cli/generator/generator::complex-multi-dependency-setup::154","title":"Generator","section":"Complex Multi-Dependency Setup","path":"/docs/guide/cli/generator/generator#complex-multi-dependency-setup","headings":["Complex Multi-Dependency Setup"],"excerpt":"Complex Multi-Dependency Setup generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myserv","content":"Complex Multi-Dependency Setup generate: inputs: - directory: \"api/proto\" plugins: # Go code generation - Core protobuf structures - name: go out: ./gen/go opts: paths: source_relative module: github.com/mycompany/myservice with_imports: true # gRPC service stubs - Server and client interfaces - name: go-grpc out: ./gen/go opts: paths: source_relative require_unimplemented_servers: false # REST Gateway - HTTP-to-gRPC proxy code - name: grpc-gateway out: ./gen/go opts: paths: source_relative # OpenAPI documentation - API specification - name: openapiv2 out: ./gen/openapi opts: simple_operation_ids: true # Validation code - Input validation functions - name: validate-go out: ./gen/go opts: paths: source_relative ```"},{"id":"cli/generator/generator::dependency-cache-integration::155","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration The generator leverages EasyP's module cache for fast builds:","content":"Dependency Cache Integration The generator leverages EasyP's module cache for fast builds:"},{"id":"cli/generator/generator::dependency-cache-integration::156","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration ```bash Download dependencies once easyp mod download","content":"Dependency Cache Integration ```bash Download dependencies once easyp mod download"},{"id":"cli/generator/generator::dependency-cache-integration::157","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration Generate code (uses cached dependencies) easyp generate","content":"Dependency Cache Integration Generate code (uses cached dependencies) easyp generate"},{"id":"cli/generator/generator::dependency-cache-integration::158","title":"Generator","section":"Dependency Cache Integration","path":"/docs/guide/cli/generator/generator#dependency-cache-integration","headings":["Dependency Cache Integration"],"excerpt":"Dependency Cache Integration Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Dependency Cache Integration Dependencies are cached in ~/.easyp/mod/ ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/generator/generator::remote-generation::159","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation Remote generation is a powerful feature that allows you to generate code from proto files hosted in remote Git repositories without requiring a local checkout. This enables true microservices architectu","content":"Remote Generation Remote generation is a powerful feature that allows you to generate code from proto files hosted in remote Git repositories without requiring a local checkout. This enables true microservices architecture where teams can consume each other's APIs without tight coupling."},{"id":"cli/generator/generator::remote-generation::160","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation **Key advantages:** **Decoupled development**: Teams can work independently while consuming each other's APIs **Version control**: Pin to specific versions of external APIs for stability **Reduced repos","content":"Remote Generation **Key advantages:** **Decoupled development**: Teams can work independently while consuming each other's APIs **Version control**: Pin to specific versions of external APIs for stability **Reduced repository size**: No need to vendor or submodule external proto files **Automatic updates**: Easy to update to newer versions when ready"},{"id":"cli/generator/generator::remote-generation::161","title":"Generator","section":"Remote Generation","path":"/docs/guide/cli/generator/generator#remote-generation","headings":["Remote Generation"],"excerpt":"Remote Generation **Best practices:** Always use tagged versions in production environments Test with latest versions in development, but pin in production Use semantic versioning when available for easier dependency man","content":"Remote Generation **Best practices:** Always use tagged versions in production environments Test with latest versions in development, but pin in production Use semantic versioning when available for easier dependency management Consider the network implications for CI/CD systems"},{"id":"cli/generator/generator::remote-proto-sources::162","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources Generate from remote repositories directly. This is particularly useful in microservices architectures where different teams own different proto definitions.","content":"Remote Proto Sources Generate from remote repositories directly. This is particularly useful in microservices architectures where different teams own different proto definitions."},{"id":"cli/generator/generator::remote-proto-sources::163","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources **Typical workflow:** Team A publishes proto definitions in a Git repository with proper versioning Team B references these protos in their easyp.yaml configuration During generation, EasyP automatic","content":"Remote Proto Sources **Typical workflow:** Team A publishes proto definitions in a Git repository with proper versioning Team B references these protos in their easyp.yaml configuration During generation, EasyP automatically fetches and uses the remote protos Generated code includes client libraries for Team A's services"},{"id":"cli/generator/generator::remote-proto-sources::164","title":"Generator","section":"Remote Proto Sources","path":"/docs/guide/cli/generator/generator#remote-proto-sources","headings":["Remote Proto Sources"],"excerpt":"Remote Proto Sources Here's a practical example showing how to combine local and remote proto sources in a single generation configuration:","content":"Remote Proto Sources Here's a practical example showing how to combine local and remote proto sources in a single generation configuration:"},{"id":"cli/generator/generator::remote-generation-use-cases::165","title":"Generator","section":"Remote Generation Use Cases","path":"/docs/guide/cli/generator/generator#remote-generation-use-cases","headings":["Remote Generation Use Cases"],"excerpt":"Remote Generation Use Cases These examples demonstrate real-world scenarios where remote generation provides significant value in distributed development environments.","content":"Remote Generation Use Cases These examples demonstrate real-world scenarios where remote generation provides significant value in distributed development environments."},{"id":"cli/generator/generator::multi-team-development::166","title":"Generator","section":"Multi-Team Development","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Multi-Team Development"],"excerpt":"Multi-Team Development Multi-team development is where remote generation truly shines. Instead of coordinating shared repositories or complex dependency management, teams can independently evolve their APIs while consume","content":"Multi-Team Development Multi-team development is where remote generation truly shines. Instead of coordinating shared repositories or complex dependency management, teams can independently evolve their APIs while consumers automatically get updates through versioned dependencies."},{"id":"cli/generator/generator::multi-team-development::167","title":"Generator","section":"Multi-Team Development","path":"/docs/guide/cli/generator/generator#multi-team-development","headings":["Multi-Team Development"],"excerpt":"Multi-Team Development This pattern is especially valuable in large organizations where: Teams have different release cycles and development velocities API ownership is clearly defined but consumption is widespread You w","content":"Multi-Team Development This pattern is especially valuable in large organizations where: Teams have different release cycles and development velocities API ownership is clearly defined but consumption is widespread You want to avoid the overhead of coordinating shared proto repositories Different teams use different technology stacks but need to communicate"},{"id":"cli/generator/generator::vendor-api-integration::168","title":"Generator","section":"Vendor API Integration","path":"/docs/guide/cli/generator/generator#vendor-api-integration","headings":["Vendor API Integration"],"excerpt":"Vendor API Integration Many vendors now provide proto definitions for their APIs, enabling strongly-typed client generation instead of relying on hand-written HTTP clients. This approach provides better type safety, auto","content":"Vendor API Integration Many vendors now provide proto definitions for their APIs, enabling strongly-typed client generation instead of relying on hand-written HTTP clients. This approach provides better type safety, automatic serialization, and often better performance."},{"id":"cli/generator/generator::vendor-api-integration::169","title":"Generator","section":"Vendor API Integration","path":"/docs/guide/cli/generator/generator#vendor-api-integration","headings":["Vendor API Integration"],"excerpt":"Vendor API Integration Benefits of using vendor proto definitions: **Type safety**: Compile-time checking of API calls and data structures **Automatic updates**: New API features become available through version updates ","content":"Vendor API Integration Benefits of using vendor proto definitions: **Type safety**: Compile-time checking of API calls and data structures **Automatic updates**: New API features become available through version updates **Consistency**: Same interface patterns across different vendor integrations **Performance**: Binary serialization is often faster than JSON **Documentation**: Proto files serve as authoritative API documentation"},{"id":"cli/generator/generator::commands::170","title":"Generator","section":"Commands","path":"/docs/guide/cli/generator/generator#commands","headings":["Commands"],"excerpt":"Commands The EasyP command-line interface provides flexible options for running code generation with different configurations and environments.","content":"Commands The EasyP command-line interface provides flexible options for running code generation with different configurations and environments."},{"id":"cli/generator/generator::basic-generation::171","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation These are the most commonly used command patterns for everyday development and production use:","content":"Basic Generation These are the most commonly used command patterns for everyday development and production use:"},{"id":"cli/generator/generator::basic-generation::172","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation ```bash Use default easyp.yaml configuration - Most common for development easyp generate","content":"Basic Generation ```bash Use default easyp.yaml configuration - Most common for development easyp generate"},{"id":"cli/generator/generator::basic-generation::173","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate","content":"Basic Generation Use custom configuration file - Essential for multi-environment setups easyp --cfg production.easyp.yaml generate"},{"id":"cli/generator/generator::basic-generation::174","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate","content":"Basic Generation Generate with debug logs - Helpful for debugging and CI/CD easyp --debug generate"},{"id":"cli/generator/generator::basic-generation::175","title":"Generator","section":"Basic Generation","path":"/docs/guide/cli/generator/generator#basic-generation","headings":["Basic Generation"],"excerpt":"Basic Generation Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```","content":"Basic Generation Generate with custom cache location - Useful for CI systems or shared environments EASYPPATH=/tmp/easyp-cache easyp generate ```"},{"id":"cli/generator/generator::integration-with-package-manager::176","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager EasyP's package manager integration means you can either explicitly manage dependencies or let the generator handle them automatically. The explicit approach gives you more control, while","content":"Integration with Package Manager EasyP's package manager integration means you can either explicitly manage dependencies or let the generator handle them automatically. The explicit approach gives you more control, while the automatic approach is more convenient:"},{"id":"cli/generator/generator::integration-with-package-manager::177","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager ```bash Explicit workflow - Better for CI/CD and when you want to cache dependencies easyp mod download # Download and cache dependencies first easyp generate # Generate code using cached","content":"Integration with Package Manager ```bash Explicit workflow - Better for CI/CD and when you want to cache dependencies easyp mod download # Download and cache dependencies first easyp generate # Generate code using cached dependencies"},{"id":"cli/generator/generator::integration-with-package-manager::178","title":"Generator","section":"Integration with Package Manager","path":"/docs/guide/cli/generator/generator#integration-with-package-manager","headings":["Integration with Package Manager"],"excerpt":"Integration with Package Manager Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```","content":"Integration with Package Manager Automatic workflow - Convenient for development (generate downloads dependencies automatically) easyp generate ```"},{"id":"cli/generator/generator::advanced-usage::179","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage These advanced usage patterns are useful for specific deployment scenarios, debugging, or when you need fine-grained control over the generation process:","content":"Advanced Usage These advanced usage patterns are useful for specific deployment scenarios, debugging, or when you need fine-grained control over the generation process:"},{"id":"cli/generator/generator::advanced-usage::180","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage ```bash Generate from specific input directory - Override config file settings easyp generate --path=./api/proto","content":"Advanced Usage ```bash Generate from specific input directory - Override config file settings easyp generate --path=./api/proto"},{"id":"cli/generator/generator::advanced-usage::181","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage Generate using vendored dependencies - For offline builds or Docker containers easyp mod vendor easyp generate","content":"Advanced Usage Generate using vendored dependencies - For offline builds or Docker containers easyp mod vendor easyp generate"},{"id":"cli/generator/generator::advanced-usage::182","title":"Generator","section":"Advanced Usage","path":"/docs/guide/cli/generator/generator#advanced-usage","headings":["Advanced Usage"],"excerpt":"Advanced Usage Generate from a custom project root - Useful in monorepos or nested workdirs easyp generate --root=/usr/local/src/my-project --path=./api/proto ```","content":"Advanced Usage Generate from a custom project root - Useful in monorepos or nested workdirs easyp generate --root=/usr/local/src/my-project --path=./api/proto ```"},{"id":"cli/generator/generator::common-patterns::183","title":"Generator","section":"Common Patterns","path":"/docs/guide/cli/generator/generator#common-patterns","headings":["Common Patterns"],"excerpt":"Common Patterns These patterns represent real-world scenarios and best practices for organizing code generation in different project structures.","content":"Common Patterns These patterns represent real-world scenarios and best practices for organizing code generation in different project structures."},{"id":"cli/generator/generator::multi-language-generation::184","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation Multi-language generation is essential for organizations using different technologies across their stack. EasyP makes it easy to generate consistent client libraries and types for multiple progr","content":"Multi-Language Generation Multi-language generation is essential for organizations using different technologies across their stack. EasyP makes it easy to generate consistent client libraries and types for multiple programming languages from the same proto definitions."},{"id":"cli/generator/generator::multi-language-generation::185","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Common scenarios:** **Full-stack applications**: Go/Java backend with TypeScript frontend for web apps **Data platforms**: Go services with Python data science tools and analysis scripts **Mic","content":"Multi-Language Generation **Common scenarios:** **Full-stack applications**: Go/Java backend with TypeScript frontend for web apps **Data platforms**: Go services with Python data science tools and analysis scripts **Microservices**: Different services implemented in optimal languages for their domain **Client libraries**: Providing SDKs in multiple languages for external developers **Legacy integration**: Modern gRPC services with legacy systems using different languages"},{"id":"cli/generator/generator::multi-language-generation::186","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Performance considerations:** Each plugin runs independently, so generation time scales linearly with plugin count Consider using parallel execution (make -j4) for large numbers of plugins Out","content":"Multi-Language Generation **Performance considerations:** Each plugin runs independently, so generation time scales linearly with plugin count Consider using parallel execution (make -j4) for large numbers of plugins Output directories should be organized hierarchically to avoid file conflicts Some plugins are faster than others - profile your build to identify bottlenecks"},{"id":"cli/generator/generator::multi-language-generation::187","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Maintenance benefits:** Single source of truth for API definitions prevents schema drift Consistent types across all languages reduce integration bugs Automatic synchronization when proto defi","content":"Multi-Language Generation **Maintenance benefits:** Single source of truth for API definitions prevents schema drift Consistent types across all languages reduce integration bugs Automatic synchronization when proto definitions change eliminates manual updates Reduced chance of API drift between different language implementations Easier refactoring since changes propagate to all generated code"},{"id":"cli/generator/generator::multi-language-generation::188","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation This example shows a typical multi-language setup for a full-stack application with backend services, web frontend, data analysis, and documentation:","content":"Multi-Language Generation This example shows a typical multi-language setup for a full-stack application with backend services, web frontend, data analysis, and documentation:"},{"id":"cli/generator/generator::multi-language-generation::189","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation **Organization tip:** Use separate output directories for each language to avoid file conflicts and make it easier to integrate with language-specific build systems.","content":"Multi-Language Generation **Organization tip:** Use separate output directories for each language to avoid file conflicts and make it easier to integrate with language-specific build systems."},{"id":"cli/generator/generator::multi-language-generation::190","title":"Generator","section":"Multi-Language Generation","path":"/docs/guide/cli/generator/generator#multi-language-generation","headings":["Multi-Language Generation"],"excerpt":"Multi-Language Generation The EasyP generator provides a comprehensive solution for protocol buffer code generation, supporting everything from simple local development to complex enterprise multi-language workflows with","content":"Multi-Language Generation The EasyP generator provides a comprehensive solution for protocol buffer code generation, supporting everything from simple local development to complex enterprise multi-language workflows with remote dependencies."},{"id":"cli/linter/linter::why-use-a-linter-for-proto-files::0","title":"Linter","section":"Why Use a Linter for Proto Files?","path":"/docs/guide/cli/linter/linter#why-use-a-linter-for-proto-files","headings":["Why Use a Linter for Proto Files?"],"excerpt":"Why Use a Linter for Proto Files? Linters play a crucial role in modern software development, particularly for proto files. By enforcing style and formatting rules, linters help maintain code quality, reduce potential bu","content":"Why Use a Linter for Proto Files? Linters play a crucial role in modern software development, particularly for proto files. By enforcing style and formatting rules, linters help maintain code quality, reduce potential bugs, and ensure that the codebase is clean and readable. This leads to several benefits:"},{"id":"cli/linter/linter::why-use-a-linter-for-proto-files::1","title":"Linter","section":"Why Use a Linter for Proto Files?","path":"/docs/guide/cli/linter/linter#why-use-a-linter-for-proto-files","headings":["Why Use a Linter for Proto Files?"],"excerpt":"Why Use a Linter for Proto Files? **Reduced Development Costs:** Linters catch errors early in the development cycle, saving time and resources that would be spent on debugging and fixing issues later. **Improved Team Co","content":"Why Use a Linter for Proto Files? **Reduced Development Costs:** Linters catch errors early in the development cycle, saving time and resources that would be spent on debugging and fixing issues later. **Improved Team Collaboration:** A standardized codebase makes it easier for team members to understand and work with each other's code, facilitating a smoother collaborative environment. **Business Efficiency:** Teams using linters often produce higher quality code, which translates to fewer production issues and maintenance costs. This makes businesses that adopt linting practices more competitive and cost-effective."},{"id":"cli/linter/linter::configuration-reference::2","title":"Linter","section":"Configuration Reference","path":"/docs/guide/cli/linter/linter#configuration-reference","headings":["Configuration Reference"],"excerpt":"Configuration Reference EasyP linter provides flexible configuration options to adapt to different project requirements. All configuration is done through the lint section in your easyp.yaml file.","content":"Configuration Reference EasyP linter provides flexible configuration options to adapt to different project requirements. All configuration is done through the lint section in your easyp.yaml file."},{"id":"cli/linter/linter::complete-configuration-example::3","title":"Linter","section":"Complete Configuration Example","path":"/docs/guide/cli/linter/linter#complete-configuration-example","headings":["Complete Configuration Example"],"excerpt":"Complete Configuration Example","content":"Complete Configuration Example"},{"id":"cli/linter/linter::use-string::4","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Specifies which linter rules or rule categories to apply. You can mix individual rules with predefined categories.","content":"use ([]string) Specifies which linter rules or rule categories to apply. You can mix individual rules with predefined categories."},{"id":"cli/linter/linter::use-string::5","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Available categories:** **MINIMAL**: Basic package consistency checks **BASIC**: Naming conventions and usage patterns **DEFAULT**: Recommended rules for most projects **COMMENTS**: Comment presence and ","content":"use ([]string) **Available categories:** **MINIMAL**: Basic package consistency checks **BASIC**: Naming conventions and usage patterns **DEFAULT**: Recommended rules for most projects **COMMENTS**: Comment presence and formatting **UNARY_RPC**: Restrictions on streaming RPCs"},{"id":"cli/linter/linter::use-string::6","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Individual rules**: Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)","content":"use ([]string) **Individual rules**: Any specific rule name (e.g., ENUM_PASCAL_CASE, FIELD_LOWER_SNAKE_CASE)"},{"id":"cli/linter/linter::use-string::7","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) **Examples:** ```yaml Use predefined categories use: [MINIMAL, BASIC, DEFAULT]","content":"use ([]string) **Examples:** ```yaml Use predefined categories use: [MINIMAL, BASIC, DEFAULT]"},{"id":"cli/linter/linter::use-string::8","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Mix categories with individual rules use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE","content":"use ([]string) Mix categories with individual rules use: - MINIMAL - COMMENT_SERVICE - COMMENT_RPC - ENUM_PASCAL_CASE"},{"id":"cli/linter/linter::use-string::9","title":"Linter","section":"use ([]string)","path":"/docs/guide/cli/linter/linter#use-string","headings":["use ([]string)"],"excerpt":"use ([]string) Use only specific rules use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```","content":"use ([]string) Use only specific rules use: - PACKAGE_DEFINED - SERVICE_PASCAL_CASE - FIELD_LOWER_SNAKE_CASE ```"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::10","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) Defines the required suffix for zero-value enum entries. This enforces a consistent naming pattern for the default enum value.","content":"enum_zero_value_suffix (string) Defines the required suffix for zero-value enum entries. This enforces a consistent naming pattern for the default enum value."},{"id":"cli/linter/linter::enum_zero_value_suffix-string::11","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\"","content":"enum_zero_value_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"UNSPECIFIED\", \"UNKNOWN\", \"DEFAULT\""},{"id":"cli/linter/linter::enum_zero_value_suffix-string::12","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) **Example:**","content":"enum_zero_value_suffix (string) **Example:**"},{"id":"cli/linter/linter::enum_zero_value_suffix-string::13","title":"Linter","section":"enum_zero_value_suffix (string)","path":"/docs/guide/cli/linter/linter#enum_zero_value_suffix-string","headings":["enum_zero_value_suffix (string)"],"excerpt":"enum_zero_value_suffix (string) With this setting, enum definitions must follow this pattern:","content":"enum_zero_value_suffix (string) With this setting, enum definitions must follow this pattern:"},{"id":"cli/linter/linter::service_suffix-string::14","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) Specifies the required suffix for service names. This ensures consistent service naming across your project.","content":"service_suffix (string) Specifies the required suffix for service names. This ensures consistent service naming across your project."},{"id":"cli/linter/linter::service_suffix-string::15","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"Service\", \"API\", \"Svc\"","content":"service_suffix (string) **Default**: Empty (no suffix required) **Common values**: \"Service\", \"API\", \"Svc\""},{"id":"cli/linter/linter::service_suffix-string::16","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) **Example:**","content":"service_suffix (string) **Example:**"},{"id":"cli/linter/linter::service_suffix-string::17","title":"Linter","section":"service_suffix (string)","path":"/docs/guide/cli/linter/linter#service_suffix-string","headings":["service_suffix (string)"],"excerpt":"service_suffix (string) With this setting, service definitions must follow this pattern:","content":"service_suffix (string) With this setting, service definitions must follow this pattern:"},{"id":"cli/linter/linter::ignore-string::18","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) Lists directories or file paths to completely exclude from linting. Supports glob patterns and relative paths from the project root.","content":"ignore ([]string) Lists directories or file paths to completely exclude from linting. Supports glob patterns and relative paths from the project root."},{"id":"cli/linter/linter::ignore-string::19","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Use cases:** Third-party or vendor proto files Generated proto files Legacy code being phased out Test fixtures that intentionally violate rules","content":"ignore ([]string) **Use cases:** Third-party or vendor proto files Generated proto files Legacy code being phased out Test fixtures that intentionally violate rules"},{"id":"cli/linter/linter::ignore-string::20","title":"Linter","section":"ignore ([]string)","path":"/docs/guide/cli/linter/linter#ignore-string","headings":["ignore ([]string)"],"excerpt":"ignore ([]string) **Examples:**","content":"ignore ([]string) **Examples:**"},{"id":"cli/linter/linter::except-string::21","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) Disables specific rules globally across the entire project. Use this when certain rules don't fit your project's conventions.","content":"except ([]string) Disables specific rules globally across the entire project. Use this when certain rules don't fit your project's conventions."},{"id":"cli/linter/linter::except-string::22","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) **When to use:** Legacy projects with established naming conventions Projects with specific style requirements Gradual adoption of linting rules","content":"except ([]string) **When to use:** Legacy projects with established naming conventions Projects with specific style requirements Gradual adoption of linting rules"},{"id":"cli/linter/linter::except-string::23","title":"Linter","section":"except ([]string)","path":"/docs/guide/cli/linter/linter#except-string","headings":["except ([]string)"],"excerpt":"except ([]string) **Examples:**","content":"except ([]string) **Examples:**"},{"id":"cli/linter/linter::allow_comment_ignores-bool::24","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) Enables or disables the ability to ignore specific rules using inline comments in proto files.","content":"allow_comment_ignores (bool) Enables or disables the ability to ignore specific rules using inline comments in proto files."},{"id":"cli/linter/linter::allow_comment_ignores-bool::25","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) **Default**: false **Recommended**: true for flexibility during development","content":"allow_comment_ignores (bool) **Default**: false **Recommended**: true for flexibility during development"},{"id":"cli/linter/linter::allow_comment_ignores-bool::26","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) **Example:**","content":"allow_comment_ignores (bool) **Example:**"},{"id":"cli/linter/linter::allow_comment_ignores-bool::27","title":"Linter","section":"allow_comment_ignores (bool)","path":"/docs/guide/cli/linter/linter#allow_comment_ignores-bool","headings":["allow_comment_ignores (bool)"],"excerpt":"allow_comment_ignores (bool) When enabled, you can use comments to ignore rules on specific elements:","content":"allow_comment_ignores (bool) When enabled, you can use comments to ignore rules on specific elements:"},{"id":"cli/linter/linter::ignore_only-mapstringstring::28","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) Allows you to disable specific rules only for certain files or directories, while keeping them active elsewhere.","content":"ignore_only (mapstringstring) Allows you to disable specific rules only for certain files or directories, while keeping them active elsewhere."},{"id":"cli/linter/linter::ignore_only-mapstringstring::29","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Use cases:** Legacy code that can't be easily updated Third-party protos with different conventions Generated code that doesn't follow your style Gradual migration strategies","content":"ignore_only (mapstringstring) **Use cases:** Legacy code that can't be easily updated Third-party protos with different conventions Generated code that doesn't follow your style Gradual migration strategies"},{"id":"cli/linter/linter::ignore_only-mapstringstring::30","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Format**: rule_name: [list_of_paths]","content":"ignore_only (mapstringstring) **Format**: rule_name: [list_of_paths]"},{"id":"cli/linter/linter::ignore_only-mapstringstring::31","title":"Linter","section":"ignore_only (map[string][]string)","path":"/docs/guide/cli/linter/linter#ignore_only-mapstringstring","headings":["ignore_only (map[string][]string)"],"excerpt":"ignore_only (mapstringstring) **Examples:**","content":"ignore_only (mapstringstring) **Examples:**"},{"id":"cli/linter/linter::comment-based-rule-ignoring::32","title":"Linter","section":"Comment-Based Rule Ignoring","path":"/docs/guide/cli/linter/linter#comment-based-rule-ignoring","headings":["Comment-Based Rule Ignoring"],"excerpt":"Comment-Based Rule Ignoring When allow_comment_ignores is enabled, you can use inline comments to ignore specific linter rules for individual proto elements. This provides fine-grained control over rule enforcement.","content":"Comment-Based Rule Ignoring When allow_comment_ignores is enabled, you can use inline comments to ignore specific linter rules for individual proto elements. This provides fine-grained control over rule enforcement."},{"id":"cli/linter/linter::supported-comment-formats::33","title":"Linter","section":"Supported Comment Formats","path":"/docs/guide/cli/linter/linter#supported-comment-formats","headings":["Supported Comment Formats"],"excerpt":"Supported Comment Formats EasyP supports two comment formats for maximum compatibility:","content":"Supported Comment Formats EasyP supports two comment formats for maximum compatibility:"},{"id":"cli/linter/linter::ignoring-message-and-field-rules::34","title":"Linter","section":"Ignoring Message and Field Rules","path":"/docs/guide/cli/linter/linter#ignoring-message-and-field-rules","headings":["Ignoring Message and Field Rules"],"excerpt":"Ignoring Message and Field Rules","content":"Ignoring Message and Field Rules"},{"id":"cli/linter/linter::best-practices-for-comment-ignores::35","title":"Linter","section":"Best Practices for Comment Ignores","path":"/docs/guide/cli/linter/linter#best-practices-for-comment-ignores","headings":["Best Practices for Comment Ignores"],"excerpt":"Best Practices for Comment Ignores","content":"Best Practices for Comment Ignores"},{"id":"cli/linter/linter::use-sparingly::36","title":"Linter","section":"Use Sparingly","path":"/docs/guide/cli/linter/linter#use-sparingly","headings":["Use Sparingly"],"excerpt":"Use Sparingly Comment ignores should be the exception, not the rule. Overuse indicates that your linting configuration may need adjustment.","content":"Use Sparingly Comment ignores should be the exception, not the rule. Overuse indicates that your linting configuration may need adjustment."},{"id":"cli/linter/linter::add-explanatory-comments::37","title":"Linter","section":"Add Explanatory Comments","path":"/docs/guide/cli/linter/linter#add-explanatory-comments","headings":["Add Explanatory Comments"],"excerpt":"Add Explanatory Comments Always explain why you're ignoring a rule to help future maintainers understand the decision.","content":"Add Explanatory Comments Always explain why you're ignoring a rule to help future maintainers understand the decision."},{"id":"cli/linter/linter::prefer-configuration-over-comments::38","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments When multiple files need the same rule ignored, use ignore_only configuration instead of individual comments.","content":"Prefer Configuration Over Comments When multiple files need the same rule ignored, use ignore_only configuration instead of individual comments."},{"id":"cli/linter/linter::prefer-configuration-over-comments::39","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments **Instead of:** ```proto // In file1.proto // buf:lint:ignore COMMENT_SERVICE service API1 { ... }","content":"Prefer Configuration Over Comments **Instead of:** ```proto // In file1.proto // buf:lint:ignore COMMENT_SERVICE service API1 { ... }"},{"id":"cli/linter/linter::prefer-configuration-over-comments::40","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments // In file2.proto // buf:lint:ignore COMMENT_SERVICE service API2 { ... } ```","content":"Prefer Configuration Over Comments // In file2.proto // buf:lint:ignore COMMENT_SERVICE service API2 { ... } ```"},{"id":"cli/linter/linter::prefer-configuration-over-comments::41","title":"Linter","section":"Prefer Configuration Over Comments","path":"/docs/guide/cli/linter/linter#prefer-configuration-over-comments","headings":["Prefer Configuration Over Comments"],"excerpt":"Prefer Configuration Over Comments **Use:**","content":"Prefer Configuration Over Comments **Use:**"},{"id":"cli/linter/linter::linter-categories::42","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories To accommodate different project needs and preferences, EasyP linter provides predefined rule categories. These categories group together various rules, allowing teams to quickly select the level of str","content":"Linter Categories To accommodate different project needs and preferences, EasyP linter provides predefined rule categories. These categories group together various rules, allowing teams to quickly select the level of strictness or areas they want to focus on during linting."},{"id":"cli/linter/linter::linter-categories::43","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories **When to use each category:**","content":"Linter Categories **When to use each category:**"},{"id":"cli/linter/linter::linter-categories::44","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories **MINIMAL:** Essential for any proto project - ensures basic consistency and prevents fundamental issues **BASIC:** Recommended for most projects - enforces common naming conventions and best practices ","content":"Linter Categories **MINIMAL:** Essential for any proto project - ensures basic consistency and prevents fundamental issues **BASIC:** Recommended for most projects - enforces common naming conventions and best practices **DEFAULT:** Additional quality checks - useful for mature projects with established workflows **COMMENTS:** Documentation requirements - important for public APIs and team collaboration **UNARY_RPC:** Streaming restrictions - use when your architecture requires only unary RPCs"},{"id":"cli/linter/linter::linter-categories::45","title":"Linter","section":"Linter Categories","path":"/docs/guide/cli/linter/linter#linter-categories","headings":["Linter Categories"],"excerpt":"Linter Categories The available categories are: **MINIMAL:** Basic checks to ensure package consistency. **BASIC:** Additional checks for naming conventions and usage patterns. **DEFAULT:** A set of default rules that mo","content":"Linter Categories The available categories are: **MINIMAL:** Basic checks to ensure package consistency. **BASIC:** Additional checks for naming conventions and usage patterns. **DEFAULT:** A set of default rules that most projects should use. **COMMENTS:** Ensures that comments are present and properly formatted. **UNARY_RPC:** Specific rules for unary RPC services."},{"id":"cli/linter/linter::rule-groupings::46","title":"Linter","section":"Rule Groupings","path":"/docs/guide/cli/linter/linter#rule-groupings","headings":["Rule Groupings"],"excerpt":"Rule Groupings Below are the rule groupings under each category:","content":"Rule Groupings Below are the rule groupings under each category:"},{"id":"cli/linter/linter::minimal::47","title":"Linter","section":"MINIMAL","path":"/docs/guide/cli/linter/linter#minimal","headings":["MINIMAL"],"excerpt":"MINIMAL DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY","content":"MINIMAL DIRECTORY_SAME_PACKAGE PACKAGE_DEFINED PACKAGE_DIRECTORY_MATCH PACKAGE_SAME_DIRECTORY"},{"id":"cli/linter/linter::basic::48","title":"Linter","section":"BASIC","path":"/docs/guide/cli/linter/linter#basic","headings":["BASIC"],"excerpt":"BASIC ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNA","content":"BASIC ENUM_FIRST_VALUE_ZERO ENUM_NO_ALLOW_ALIAS ENUM_PASCAL_CASE ENUM_VALUE_UPPER_SNAKE_CASE FIELD_LOWER_SNAKE_CASE IMPORT_NO_PUBLIC IMPORT_NO_WEAK IMPORT_USED MESSAGE_PASCAL_CASE ONEOF_LOWER_SNAKE_CASE PACKAGE_LOWER_SNAKE_CASE PACKAGE_SAME_CSHARP_NAMESPACE PACKAGE_SAME_GO_PACKAGE PACKAGE_SAME_JAVA_MULTIPLE_FILES PACKAGE_SAME_JAVA_PACKAGE PACKAGE_SAME_PHP_NAMESPACE PACKAGE_SAME_RUBY_PACKAGE PACKAGE_SAME_SWIFT_PREFIX RPC_PASCAL_CASE SERVICE_PASCAL_CASE"},{"id":"cli/linter/linter::default::49","title":"Linter","section":"DEFAULT","path":"/docs/guide/cli/linter/linter#default","headings":["DEFAULT"],"excerpt":"DEFAULT ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX","content":"DEFAULT ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX FILE_LOWER_SNAKE_CASE RPC_REQUEST_RESPONSE_UNIQUE RPC_REQUEST_STANDARD_NAME RPC_RESPONSE_STANDARD_NAME PACKAGE_VERSION_SUFFIX SERVICE_SUFFIX"},{"id":"cli/linter/linter::comments::50","title":"Linter","section":"COMMENTS","path":"/docs/guide/cli/linter/linter#comments","headings":["COMMENTS"],"excerpt":"COMMENTS COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE","content":"COMMENTS COMMENT_ENUM COMMENT_ENUM_VALUE COMMENT_FIELD COMMENT_MESSAGE COMMENT_ONEOF COMMENT_RPC COMMENT_SERVICE"},{"id":"cli/linter/linter::unary_rpc::51","title":"Linter","section":"UNARY_RPC","path":"/docs/guide/cli/linter/linter#unary_rpc","headings":["UNARY_RPC"],"excerpt":"UNARY_RPC RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING","content":"UNARY_RPC RPC_NO_CLIENT_STREAMING RPC_NO_SERVER_STREAMING"},{"id":"cli/linter/linter::conclusion::52","title":"Linter","section":"Conclusion","path":"/docs/guide/cli/linter/linter#conclusion","headings":["Conclusion"],"excerpt":"Conclusion Adopting the EasyP linter for your proto files can significantly enhance your development workflow, code quality, and overall project maintainability. With full compatibility with the Buf linter, teams can eas","content":"Conclusion Adopting the EasyP linter for your proto files can significantly enhance your development workflow, code quality, and overall project maintainability. With full compatibility with the Buf linter, teams can easily migrate and start benefiting from our tool's robust features and flexible configuration options."},{"id":"cli/linter/rules/comment-enum-value::top::0","title":"COMMENT_ENUM_VALUE","path":"/docs/guide/cli/linter/rules/comment-enum-value","headings":[],"excerpt":"This rule checks that enum values have a comment.","content":"This rule checks that enum values have a comment."},{"id":"cli/linter/rules/comment-enum-value::bad::1","title":"COMMENT_ENUM_VALUE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum-value#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum-value::bad::2","title":"COMMENT_ENUM_VALUE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum-value#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum-value::good::3","title":"COMMENT_ENUM_VALUE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum-value#good","headings":["Good"],"excerpt":"Good enum Foo { // BAR value for bar logic // [!code focus] BAR = 0; // BAZ value for baz logic // [!code focus] BAZ = 1; } ```","content":"Good enum Foo { // BAR value for bar logic // [!code focus] BAR = 0; // BAZ value for baz logic // [!code focus] BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum::top::0","title":"COMMENT_ENUM","path":"/docs/guide/cli/linter/rules/comment-enum","headings":[],"excerpt":"This rule checks that enum has a comment.","content":"This rule checks that enum has a comment."},{"id":"cli/linter/rules/comment-enum::bad::1","title":"COMMENT_ENUM","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum::bad::2","title":"COMMENT_ENUM","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-enum#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-enum::good::3","title":"COMMENT_ENUM","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-enum::good::4","title":"COMMENT_ENUM","section":"Good","path":"/docs/guide/cli/linter/rules/comment-enum#good","headings":["Good"],"excerpt":"Good // Foo enum for bar and baz logic // [!code focus] enum Foo { BAR = 0; BAZ = 1; } ```","content":"Good // Foo enum for bar and baz logic // [!code focus] enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/comment-field::top::0","title":"COMMENT_FIELD","path":"/docs/guide/cli/linter/rules/comment-field","headings":[],"excerpt":"This rule checks that all message fields have a comment.","content":"This rule checks that all message fields have a comment."},{"id":"cli/linter/rules/comment-field::bad::1","title":"COMMENT_FIELD","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-field#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-field::bad::2","title":"COMMENT_FIELD","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-field#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; string baz = 2; } ```","content":"Bad message Foo { string bar = 1; string baz = 2; } ```"},{"id":"cli/linter/rules/comment-field::good::3","title":"COMMENT_FIELD","section":"Good","path":"/docs/guide/cli/linter/rules/comment-field#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-field::good::4","title":"COMMENT_FIELD","section":"Good","path":"/docs/guide/cli/linter/rules/comment-field#good","headings":["Good"],"excerpt":"Good message Foo { // bar field for bar logic // [!code focus] string bar = 1; // baz field for baz logic // [!code focus] string baz = 2; } ```","content":"Good message Foo { // bar field for bar logic // [!code focus] string bar = 1; // baz field for baz logic // [!code focus] string baz = 2; } ```"},{"id":"cli/linter/rules/comment-message::top::0","title":"COMMENT_MESSAGE","path":"/docs/guide/cli/linter/rules/comment-message","headings":[],"excerpt":"This rule checks that message has a comment.","content":"This rule checks that message has a comment."},{"id":"cli/linter/rules/comment-message::bad::1","title":"COMMENT_MESSAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-message#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; string baz = 2; } ```","content":"Bad message Foo { string bar = 1; string baz = 2; } ```"},{"id":"cli/linter/rules/comment-message::good::2","title":"COMMENT_MESSAGE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-message#good","headings":["Good"],"excerpt":"Good // Foo message for bar and baz logic // [!code focus] message Foo { // bar field for bar logic string bar = 1; // baz field for baz logic string baz = 2; } ```","content":"Good // Foo message for bar and baz logic // [!code focus] message Foo { // bar field for bar logic string bar = 1; // baz field for baz logic string baz = 2; } ```"},{"id":"cli/linter/rules/comment-oneof::top::0","title":"COMMENT_ONEOF","path":"/docs/guide/cli/linter/rules/comment-oneof","headings":[],"excerpt":"This rule checks that oneof has a comment.","content":"This rule checks that oneof has a comment."},{"id":"cli/linter/rules/comment-oneof::bad::1","title":"COMMENT_ONEOF","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-oneof#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-oneof::bad::2","title":"COMMENT_ONEOF","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-oneof#bad","headings":["Bad"],"excerpt":"Bad message Foo { oneof bar { string baz = 1; string qux = 2; } } ```","content":"Bad message Foo { oneof bar { string baz = 1; string qux = 2; } } ```"},{"id":"cli/linter/rules/comment-oneof::good::3","title":"COMMENT_ONEOF","section":"Good","path":"/docs/guide/cli/linter/rules/comment-oneof#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-oneof::good::4","title":"COMMENT_ONEOF","section":"Good","path":"/docs/guide/cli/linter/rules/comment-oneof#good","headings":["Good"],"excerpt":"Good message Foo { // bar oneof for baz and qux logic // [!code focus] oneof bar { string baz = 1; string qux = 2; } } ```","content":"Good message Foo { // bar oneof for baz and qux logic // [!code focus] oneof bar { string baz = 1; string qux = 2; } } ```"},{"id":"cli/linter/rules/comment-rpc::top::0","title":"COMMENT_RPC","path":"/docs/guide/cli/linter/rules/comment-rpc","headings":[],"excerpt":"This rule checks that rpc has a comment.","content":"This rule checks that rpc has a comment."},{"id":"cli/linter/rules/comment-rpc::bad::1","title":"COMMENT_RPC","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-rpc#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-rpc::bad::2","title":"COMMENT_RPC","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-rpc#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} rpc Baz (BazRequest) returns (BazResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} rpc Baz (BazRequest) returns (BazResponse) {} } ```"},{"id":"cli/linter/rules/comment-rpc::good::3","title":"COMMENT_RPC","section":"Good","path":"/docs/guide/cli/linter/rules/comment-rpc#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-rpc::good::4","title":"COMMENT_RPC","section":"Good","path":"/docs/guide/cli/linter/rules/comment-rpc#good","headings":["Good"],"excerpt":"Good service Foo { // Bar rpc for bar logic // [!code focus] rpc Bar (BarRequest) returns (BarResponse) {} // Baz rpc for baz logic // [!code focus] rpc Baz (BazRequest) returns (BazResponse) {} } ```","content":"Good service Foo { // Bar rpc for bar logic // [!code focus] rpc Bar (BarRequest) returns (BarResponse) {} // Baz rpc for baz logic // [!code focus] rpc Baz (BazRequest) returns (BazResponse) {} } ```"},{"id":"cli/linter/rules/comment-service::top::0","title":"COMMENT_SERVICE","path":"/docs/guide/cli/linter/rules/comment-service","headings":[],"excerpt":"This rule checks that service has a comment.","content":"This rule checks that service has a comment."},{"id":"cli/linter/rules/comment-service::bad::1","title":"COMMENT_SERVICE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-service#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-service::bad::2","title":"COMMENT_SERVICE","section":"Bad","path":"/docs/guide/cli/linter/rules/comment-service#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/comment-service::good::3","title":"COMMENT_SERVICE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-service#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/comment-service::good::4","title":"COMMENT_SERVICE","section":"Good","path":"/docs/guide/cli/linter/rules/comment-service#good","headings":["Good"],"excerpt":"Good // Foo service for bar logic // [!code focus] service Foo { // Bar rpc for bar logic rpc Bar (BarRequest) returns (BarResponse) {} } ```","content":"Good // Foo service for bar logic // [!code focus] service Foo { // Bar rpc for bar logic rpc Bar (BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/directory-same-package::top::0","title":"DIRECTORY_SAME_PACKAGE","path":"/docs/guide/cli/linter/rules/directory-same-package","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/directory-same-package::top::1","title":"DIRECTORY_SAME_PACKAGE","path":"/docs/guide/cli/linter/rules/directory-same-package","headings":[],"excerpt":"This rule checks that all files in a given directory are in the same package.","content":"This rule checks that all files in a given directory are in the same package."},{"id":"cli/linter/rules/directory-same-package::bad::2","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: dir/foo.proto","content":"Bad ```proto // File: dir/foo.proto"},{"id":"cli/linter/rules/directory-same-package::bad::3","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad syntax = \"proto3\"; package foo;","content":"Bad syntax = \"proto3\"; package foo;"},{"id":"cli/linter/rules/directory-same-package::bad::4","title":"DIRECTORY_SAME_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/directory-same-package#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; } ```","content":"Bad message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/directory-same-package::good::5","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good ```proto // File: dir/foo/foo.proto // [!code focus]","content":"Good ```proto // File: dir/foo/foo.proto // [!code focus]"},{"id":"cli/linter/rules/directory-same-package::good::6","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good package dir.foo; // [!code focus]","content":"Good package dir.foo; // [!code focus]"},{"id":"cli/linter/rules/directory-same-package::good::7","title":"DIRECTORY_SAME_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/directory-same-package#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/enum-first-value-zero::top::0","title":"ENUM_FIRST_VALUE_ZERO","path":"/docs/guide/cli/linter/rules/enum-first-value-zero","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-first-value-zero::top::1","title":"ENUM_FIRST_VALUE_ZERO","path":"/docs/guide/cli/linter/rules/enum-first-value-zero","headings":[],"excerpt":"This rule checks that the first value of an enum is zero.","content":"This rule checks that the first value of an enum is zero."},{"id":"cli/linter/rules/enum-first-value-zero::bad::2","title":"ENUM_FIRST_VALUE_ZERO","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#bad","headings":["Bad"],"excerpt":"Bad enum Foo { BAR = 1; BAZ = 2; } ```","content":"Bad enum Foo { BAR = 1; BAZ = 2; } ```"},{"id":"cli/linter/rules/enum-first-value-zero::good::3","title":"ENUM_FIRST_VALUE_ZERO","section":"Good","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-first-value-zero::good::4","title":"ENUM_FIRST_VALUE_ZERO","section":"Good","path":"/docs/guide/cli/linter/rules/enum-first-value-zero#good","headings":["Good"],"excerpt":"Good enum Foo { BAR = 0; // [!code focus] BAZ = 1; } ```","content":"Good enum Foo { BAR = 0; // [!code focus] BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-no-allow-alias::top::0","title":"ENUM_NO_ALLOW_ALIAS","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-no-allow-alias::top::1","title":"ENUM_NO_ALLOW_ALIAS","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias","headings":[],"excerpt":"This rule checks that the allow_alias option is not set to true in an enum.","content":"This rule checks that the allow_alias option is not set to true in an enum."},{"id":"cli/linter/rules/enum-no-allow-alias::bad::2","title":"ENUM_NO_ALLOW_ALIAS","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-no-allow-alias::bad::3","title":"ENUM_NO_ALLOW_ALIAS","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#bad","headings":["Bad"],"excerpt":"Bad enum Foo { option allow_alias = true; // [!code focus] BAR = 0; BAZ = 1; } ```","content":"Bad enum Foo { option allow_alias = true; // [!code focus] BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-no-allow-alias::good::4","title":"ENUM_NO_ALLOW_ALIAS","section":"Good","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-no-allow-alias::good::5","title":"ENUM_NO_ALLOW_ALIAS","section":"Good","path":"/docs/guide/cli/linter/rules/enum-no-allow-alias#good","headings":["Good"],"excerpt":"Good enum Foo { BAR = 0; BAZ = 1; } ```","content":"Good enum Foo { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-pascal-case::top::0","title":"ENUM_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/enum-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-pascal-case::top::1","title":"ENUM_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/enum-pascal-case","headings":[],"excerpt":"This rule checks that enum names are in PascalCase.","content":"This rule checks that enum names are in PascalCase."},{"id":"cli/linter/rules/enum-pascal-case::bad::2","title":"ENUM_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-pascal-case::bad::3","title":"ENUM_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-pascal-case#bad","headings":["Bad"],"excerpt":"Bad enum foo_bar { BAR = 0; BAZ = 1; } ```","content":"Bad enum foo_bar { BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-pascal-case::good::4","title":"ENUM_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-pascal-case::good::5","title":"ENUM_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-pascal-case#good","headings":["Good"],"excerpt":"Good enum FooBar { // [!code focus] BAR = 0; BAZ = 1; } ```","content":"Good enum FooBar { // [!code focus] BAR = 0; BAZ = 1; } ```"},{"id":"cli/linter/rules/enum-value-prefix::top::0","title":"ENUM_VALUE_PREFIX","path":"/docs/guide/cli/linter/rules/enum-value-prefix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-value-prefix::top::1","title":"ENUM_VALUE_PREFIX","path":"/docs/guide/cli/linter/rules/enum-value-prefix","headings":[],"excerpt":"This rule checks that all enum values are prefixed with the enum name.","content":"This rule checks that all enum values are prefixed with the enum name."},{"id":"cli/linter/rules/enum-value-prefix::bad::2","title":"ENUM_VALUE_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-prefix::good::3","title":"ENUM_VALUE_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-prefix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-prefix::good::4","title":"ENUM_VALUE_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-prefix#good","headings":["Good"],"excerpt":"Good enum Foo { FOO_BAR = 0; // [!code focus] } ```","content":"Good enum Foo { FOO_BAR = 0; // [!code focus] } ```"},{"id":"cli/linter/rules/enum-value-upper-snake-case::top::0","title":"ENUM_VALUE_UPPER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-value-upper-snake-case::top::1","title":"ENUM_VALUE_UPPER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case","headings":[],"excerpt":"This rule checks that enum values are in UPPER_SNAKE_CASE.","content":"This rule checks that enum values are in UPPER_SNAKE_CASE."},{"id":"cli/linter/rules/enum-value-upper-snake-case::bad::2","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-upper-snake-case::bad::3","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#bad","headings":["Bad"],"excerpt":"Bad enum Foo { barName = 0; bazName = 1; } ```","content":"Bad enum Foo { barName = 0; bazName = 1; } ```"},{"id":"cli/linter/rules/enum-value-upper-snake-case::good::4","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-value-upper-snake-case::good::5","title":"ENUM_VALUE_UPPER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/enum-value-upper-snake-case#good","headings":["Good"],"excerpt":"Good enum Foo { BAR_NAME = 0; // [!code focus] BAZ_NAME = 1; // [!code focus] } ```","content":"Good enum Foo { BAR_NAME = 0; // [!code focus] BAZ_NAME = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/enum-zero-value-suffix::top::0","title":"ENUM_ZERO_VALUE_SUFFIX","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/enum-zero-value-suffix::top::1","title":"ENUM_ZERO_VALUE_SUFFIX","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix","headings":[],"excerpt":"This rule checks that all enum zero values are suffixed with _NONE or your custom suffix.","content":"This rule checks that all enum zero values are suffixed with _NONE or your custom suffix."},{"id":"cli/linter/rules/enum-zero-value-suffix::bad::2","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-zero-value-suffix::good::3","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/enum-zero-value-suffix::good::4","title":"ENUM_ZERO_VALUE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/enum-zero-value-suffix#good","headings":["Good"],"excerpt":"Good enum Foo { FOO_BAR_NONE = 0; // [!code focus] } ```","content":"Good enum Foo { FOO_BAR_NONE = 0; // [!code focus] } ```"},{"id":"cli/linter/rules/field-lower-snake-case::top::0","title":"FIELD_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/field-lower-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/field-lower-snake-case::top::1","title":"FIELD_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/field-lower-snake-case","headings":[],"excerpt":"This rule checks that field names of messages are in lower_snake_case.","content":"This rule checks that field names of messages are in lower_snake_case."},{"id":"cli/linter/rules/field-lower-snake-case::bad::2","title":"FIELD_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/field-lower-snake-case::bad::3","title":"FIELD_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad message Foo { string BarName = 1; } ```","content":"Bad message Foo { string BarName = 1; } ```"},{"id":"cli/linter/rules/field-lower-snake-case::good::4","title":"FIELD_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/field-lower-snake-case::good::5","title":"FIELD_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/field-lower-snake-case#good","headings":["Good"],"excerpt":"Good message Foo { string bar_name = 1; // [!code focus] } ```","content":"Good message Foo { string bar_name = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/file-lower-snake-case::top::0","title":"FILE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/file-lower-snake-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/file-lower-snake-case::top::1","title":"FILE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/file-lower-snake-case","headings":[],"excerpt":"This rule checks that all files are in lower_snake_case.","content":"This rule checks that all files are in lower_snake_case."},{"id":"cli/linter/rules/file-lower-snake-case::bad::2","title":"FILE_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/file-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/FooBaz.proto","content":"Bad ```proto // File: bar/FooBaz.proto"},{"id":"cli/linter/rules/file-lower-snake-case::good::3","title":"FILE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/file-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo_baz.proto // [!code focus]","content":"Good ```proto // File: bar/foo_baz.proto // [!code focus]"},{"id":"cli/linter/rules/import-no-public::top::0","title":"IMPORT_NO_PUBLIC","path":"/docs/guide/cli/linter/rules/import-no-public","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-no-public::top::1","title":"IMPORT_NO_PUBLIC","path":"/docs/guide/cli/linter/rules/import-no-public","headings":[],"excerpt":"This rule checks that no public imports are used in a proto file.","content":"This rule checks that no public imports are used in a proto file."},{"id":"cli/linter/rules/import-no-public::bad::2","title":"IMPORT_NO_PUBLIC","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-public#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-no-public::bad::3","title":"IMPORT_NO_PUBLIC","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-public#bad","headings":["Bad"],"excerpt":"Bad import public \"bar.proto\"; ```","content":"Bad import public \"bar.proto\"; ```"},{"id":"cli/linter/rules/import-no-public::good::4","title":"IMPORT_NO_PUBLIC","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-public#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-no-public::good::5","title":"IMPORT_NO_PUBLIC","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-public#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus] ```","content":"Good import \"bar.proto\"; // [!code focus] ```"},{"id":"cli/linter/rules/import-no-weak::top::0","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-no-weak::top::1","title":"IMPORT_NO_WEAK","path":"/docs/guide/cli/linter/rules/import-no-weak","headings":[],"excerpt":"This rule checks that no weak imports are used in a proto file.","content":"This rule checks that no weak imports are used in a proto file."},{"id":"cli/linter/rules/import-no-weak::bad::2","title":"IMPORT_NO_WEAK","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-weak#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto2\";","content":"Bad ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::bad::3","title":"IMPORT_NO_WEAK","section":"Bad","path":"/docs/guide/cli/linter/rules/import-no-weak#bad","headings":["Bad"],"excerpt":"Bad import weak \"bar.proto\"; ```","content":"Bad import weak \"bar.proto\"; ```"},{"id":"cli/linter/rules/import-no-weak::good::4","title":"IMPORT_NO_WEAK","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-weak#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto2\";","content":"Good ```proto syntax = \"proto2\";"},{"id":"cli/linter/rules/import-no-weak::good::5","title":"IMPORT_NO_WEAK","section":"Good","path":"/docs/guide/cli/linter/rules/import-no-weak#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus] ```","content":"Good import \"bar.proto\"; // [!code focus] ```"},{"id":"cli/linter/rules/import-used::top::0","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/import-used::top::1","title":"IMPORT_USED","path":"/docs/guide/cli/linter/rules/import-used","headings":[],"excerpt":"This rule checks that all imports are used in a proto file.","content":"This rule checks that all imports are used in a proto file."},{"id":"cli/linter/rules/import-used::bad::2","title":"IMPORT_USED","section":"Bad","path":"/docs/guide/cli/linter/rules/import-used#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-used::good::3","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/import-used::good::4","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good import \"bar.proto\"; // [!code focus]","content":"Good import \"bar.proto\"; // [!code focus]"},{"id":"cli/linter/rules/import-used::good::5","title":"IMPORT_USED","section":"Good","path":"/docs/guide/cli/linter/rules/import-used#good","headings":["Good"],"excerpt":"Good message Foo { bar.Bar bar = 1; // [!code focus] } ```","content":"Good message Foo { bar.Bar bar = 1; // [!code focus] } ```"},{"id":"cli/linter/rules/message-pascal-case::top::0","title":"MESSAGE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/message-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/message-pascal-case::top::1","title":"MESSAGE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/message-pascal-case","headings":[],"excerpt":"This rule checks that message names are in PascalCase.","content":"This rule checks that message names are in PascalCase."},{"id":"cli/linter/rules/message-pascal-case::bad::2","title":"MESSAGE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/message-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/message-pascal-case::bad::3","title":"MESSAGE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/message-pascal-case#bad","headings":["Bad"],"excerpt":"Bad message foo_bar { string bar_name = 1; } ```","content":"Bad message foo_bar { string bar_name = 1; } ```"},{"id":"cli/linter/rules/message-pascal-case::good::4","title":"MESSAGE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/message-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/message-pascal-case::good::5","title":"MESSAGE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/message-pascal-case#good","headings":["Good"],"excerpt":"Good message FooBar { // [!code focus] string bar_name = 1; } ```","content":"Good message FooBar { // [!code focus] string bar_name = 1; } ```"},{"id":"cli/linter/rules/oneof-lower-snake-case::top::0","title":"ONEOF_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/oneof-lower-snake-case::top::1","title":"ONEOF_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case","headings":[],"excerpt":"This rule checks that oneof names are in lower_snake_case.","content":"This rule checks that oneof names are in lower_snake_case."},{"id":"cli/linter/rules/oneof-lower-snake-case::bad::2","title":"ONEOF_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/oneof-lower-snake-case::bad::3","title":"ONEOF_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad message Foo { oneof BarName { string bar_name = 1; } } ```","content":"Bad message Foo { oneof BarName { string bar_name = 1; } } ```"},{"id":"cli/linter/rules/oneof-lower-snake-case::good::4","title":"ONEOF_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/oneof-lower-snake-case::good::5","title":"ONEOF_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/oneof-lower-snake-case#good","headings":["Good"],"excerpt":"Good message Foo { oneof bar_name { // [!code focus] string bar_name = 1; } } ```","content":"Good message Foo { oneof bar_name { // [!code focus] string bar_name = 1; } } ```"},{"id":"cli/linter/rules/package-defined::top::0","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-defined::top::1","title":"PACKAGE_DEFINED","path":"/docs/guide/cli/linter/rules/package-defined","headings":[],"excerpt":"This rule checks that all files have a package declaration.","content":"This rule checks that all files have a package declaration."},{"id":"cli/linter/rules/package-defined::bad::2","title":"PACKAGE_DEFINED","section":"Bad","path":"/docs/guide/cli/linter/rules/package-defined#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-defined::bad::3","title":"PACKAGE_DEFINED","section":"Bad","path":"/docs/guide/cli/linter/rules/package-defined#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-defined::good::4","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-defined::good::5","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good package foo; // [!code focus]","content":"Good package foo; // [!code focus]"},{"id":"cli/linter/rules/package-defined::good::6","title":"PACKAGE_DEFINED","section":"Good","path":"/docs/guide/cli/linter/rules/package-defined#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/package-directory-match::top::0","title":"PACKAGE_DIRECTORY_MATCH","path":"/docs/guide/cli/linter/rules/package-directory-match","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-directory-match::top::1","title":"PACKAGE_DIRECTORY_MATCH","path":"/docs/guide/cli/linter/rules/package-directory-match","headings":[],"excerpt":"This rule checks that all files are in a directory that matches their package name.","content":"This rule checks that all files are in a directory that matches their package name."},{"id":"cli/linter/rules/package-directory-match::bad::2","title":"PACKAGE_DIRECTORY_MATCH","section":"Bad","path":"/docs/guide/cli/linter/rules/package-directory-match#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto","content":"Bad ```proto // File: bar/foo.proto"},{"id":"cli/linter/rules/package-directory-match::bad::3","title":"PACKAGE_DIRECTORY_MATCH","section":"Bad","path":"/docs/guide/cli/linter/rules/package-directory-match#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-directory-match::good::4","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto // [!code focus]","content":"Good ```proto // File: bar/foo.proto // [!code focus]"},{"id":"cli/linter/rules/package-directory-match::good::5","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good package bar; // [!code focus]","content":"Good package bar; // [!code focus]"},{"id":"cli/linter/rules/package-directory-match::good::6","title":"PACKAGE_DIRECTORY_MATCH","section":"Good","path":"/docs/guide/cli/linter/rules/package-directory-match#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; } ```","content":"Good message Foo { string bar = 1; } ```"},{"id":"cli/linter/rules/package-lower-snake-case::top::0","title":"PACKAGE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/package-lower-snake-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-lower-snake-case::top::1","title":"PACKAGE_LOWER_SNAKE_CASE","path":"/docs/guide/cli/linter/rules/package-lower-snake-case","headings":[],"excerpt":"This rule checks that package names are in lower_snake_case.","content":"This rule checks that package names are in lower_snake_case."},{"id":"cli/linter/rules/package-lower-snake-case::bad::2","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto syntax = \"proto3\";","content":"Bad ```proto // File: bar/foo.proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-lower-snake-case::good::3","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto syntax = \"proto3\";","content":"Good ```proto // File: bar/foo.proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-lower-snake-case::good::4","title":"PACKAGE_LOWER_SNAKE_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/package-lower-snake-case#good","headings":["Good"],"excerpt":"Good package foo_bar; // [!code focus] ```","content":"Good package foo_bar; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::top::0","title":"PACKAGE_SAME_CSHARP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-csharp-namespace::top::1","title":"PACKAGE_SAME_CSHARP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace","headings":[],"excerpt":"This rule checks that all files with a given package are in the same C# namespace.","content":"This rule checks that all files with a given package are in the same C# namespace."},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::2","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::3","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad option csharp_namespace = \"Foo.Bar\"; ```","content":"Bad option csharp_namespace = \"Foo.Bar\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::4","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::bad::5","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#bad","headings":["Bad"],"excerpt":"Bad option csharp_namespace = \"Foo.Baz\"; ```","content":"Bad option csharp_namespace = \"Foo.Baz\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::6","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::7","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good option csharp_namespace = \"Foo.Bar\"; ```","content":"Good option csharp_namespace = \"Foo.Bar\"; ```"},{"id":"cli/linter/rules/package-same-csharp-namespace::good::8","title":"PACKAGE_SAME_CSHARP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-csharp-namespace#good","headings":["Good"],"excerpt":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```","content":"Good option csharp_namespace = \"Foo.Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-directory::top::0","title":"PACKAGE_SAME_DIRECTORY","path":"/docs/guide/cli/linter/rules/package-same-directory","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-directory::top::1","title":"PACKAGE_SAME_DIRECTORY","path":"/docs/guide/cli/linter/rules/package-same-directory","headings":[],"excerpt":"This rule checks that all files with a given package are in the same directory.","content":"This rule checks that all files with a given package are in the same directory."},{"id":"cli/linter/rules/package-same-directory::bad::2","title":"PACKAGE_SAME_DIRECTORY","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-directory#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: bar/foo.proto","content":"Bad ```proto // File: bar/foo.proto"},{"id":"cli/linter/rules/package-same-directory::bad::3","title":"PACKAGE_SAME_DIRECTORY","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-directory#bad","headings":["Bad"],"excerpt":"Bad message Foo { string bar = 1; }","content":"Bad message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-same-directory::good::4","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good ```proto // File: bar/foo.proto // [!code focus]","content":"Good ```proto // File: bar/foo.proto // [!code focus]"},{"id":"cli/linter/rules/package-same-directory::good::5","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good package bar; // [!code focus]","content":"Good package bar; // [!code focus]"},{"id":"cli/linter/rules/package-same-directory::good::6","title":"PACKAGE_SAME_DIRECTORY","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-directory#good","headings":["Good"],"excerpt":"Good message Foo { string bar = 1; }","content":"Good message Foo { string bar = 1; }"},{"id":"cli/linter/rules/package-same-go-package::top::0","title":"PACKAGE_SAME_GO_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-go-package","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-go-package::top::1","title":"PACKAGE_SAME_GO_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-go-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Go package.","content":"This rule checks that all files with a given package are in the same Go package."},{"id":"cli/linter/rules/package-same-go-package::bad::2","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-go-package::bad::3","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad option go_package = \"example.com/foo/bar\";","content":"Bad option go_package = \"example.com/foo/bar\";"},{"id":"cli/linter/rules/package-same-go-package::bad::4","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-go-package::bad::5","title":"PACKAGE_SAME_GO_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-go-package#bad","headings":["Bad"],"excerpt":"Bad option go_package = \"example.com/foo/baz\";","content":"Bad option go_package = \"example.com/foo/baz\";"},{"id":"cli/linter/rules/package-same-go-package::good::6","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-go-package::good::7","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```","content":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-go-package::good::8","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-go-package::good::9","title":"PACKAGE_SAME_GO_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-go-package#good","headings":["Good"],"excerpt":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```","content":"Good option go_package = \"example.com/foo/bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::0","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","content":"PACKAGE_SAME_JAVA_MULTIPLE_FILES"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::1","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-java-multiple-files::top::2","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Java package.","content":"This rule checks that all files with a given package are in the same Java package."},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::3","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::4","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.foo\"; ```","content":"Bad option java_package = \"com.example.foo\"; ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::bad::5","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.bar\"; ```","content":"Bad option java_package = \"com.example.bar\"; ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::6","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::7","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::8","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-multiple-files::good::9","title":"PACKAGE_SAME_JAVA_MULTIPLE_FILES","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-multiple-files#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-package::top::0","title":"PACKAGE_SAME_JAVA_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-java-package","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-java-package::top::1","title":"PACKAGE_SAME_JAVA_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-java-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Java package.","content":"This rule checks that all files with a given package are in the same Java package."},{"id":"cli/linter/rules/package-same-java-package::bad::2","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-package::bad::3","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.foo\"; ```","content":"Bad option java_package = \"com.example.foo\"; ```"},{"id":"cli/linter/rules/package-same-java-package::bad::4","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-package::bad::5","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-java-package#bad","headings":["Bad"],"excerpt":"Bad option java_package = \"com.example.bar\"; ```","content":"Bad option java_package = \"com.example.bar\"; ```"},{"id":"cli/linter/rules/package-same-java-package::good::6","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-java-package::good::7","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-java-package::good::8","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-java-package::good::9","title":"PACKAGE_SAME_JAVA_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-java-package#good","headings":["Good"],"excerpt":"Good option java_package = \"com.example.foo\"; // [!code focus] ```","content":"Good option java_package = \"com.example.foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-php-namespace::top::0","title":"PACKAGE_SAME_PHP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-php-namespace","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-php-namespace::top::1","title":"PACKAGE_SAME_PHP_NAMESPACE","path":"/docs/guide/cli/linter/rules/package-same-php-namespace","headings":[],"excerpt":"This rule checks that all files with a given package are in the same PHP namespace.","content":"This rule checks that all files with a given package are in the same PHP namespace."},{"id":"cli/linter/rules/package-same-php-namespace::bad::2","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-php-namespace::bad::3","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad option php_namespace = \"Foo\\\\Bar\";","content":"Bad option php_namespace = \"Foo\\\\Bar\";"},{"id":"cli/linter/rules/package-same-php-namespace::bad::4","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-php-namespace::bad::5","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#bad","headings":["Bad"],"excerpt":"Bad option php_namespace = \"Foo\\\\Baz\"; ```","content":"Bad option php_namespace = \"Foo\\\\Baz\"; ```"},{"id":"cli/linter/rules/package-same-php-namespace::good::6","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-php-namespace::good::7","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```","content":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-php-namespace::good::8","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-php-namespace::good::9","title":"PACKAGE_SAME_PHP_NAMESPACE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-php-namespace#good","headings":["Good"],"excerpt":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```","content":"Good option php_namespace = \"Foo\\\\Bar\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-ruby-package::top::0","title":"PACKAGE_SAME_RUBY_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-ruby-package","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-ruby-package::top::1","title":"PACKAGE_SAME_RUBY_PACKAGE","path":"/docs/guide/cli/linter/rules/package-same-ruby-package","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Ruby package.","content":"This rule checks that all files with a given package are in the same Ruby package."},{"id":"cli/linter/rules/package-same-ruby-package::bad::2","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-ruby-package::bad::3","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad option ruby_package = \"Foo\"; ```","content":"Bad option ruby_package = \"Foo\"; ```"},{"id":"cli/linter/rules/package-same-ruby-package::bad::4","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-ruby-package::bad::5","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#bad","headings":["Bad"],"excerpt":"Bad option ruby_package = \"Bar\"; ```","content":"Bad option ruby_package = \"Bar\"; ```"},{"id":"cli/linter/rules/package-same-ruby-package::good::6","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-ruby-package::good::7","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good option ruby_package = \"Foo\"; // [!code focus] ```","content":"Good option ruby_package = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-ruby-package::good::8","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-ruby-package::good::9","title":"PACKAGE_SAME_RUBY_PACKAGE","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-ruby-package#good","headings":["Good"],"excerpt":"Good option ruby_package = \"Foo\"; // [!code focus] ```","content":"Good option ruby_package = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-swift-prefix::top::0","title":"PACKAGE_SAME_SWIFT_PREFIX","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-same-swift-prefix::top::1","title":"PACKAGE_SAME_SWIFT_PREFIX","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix","headings":[],"excerpt":"This rule checks that all files with a given package are in the same Swift prefix.","content":"This rule checks that all files with a given package are in the same Swift prefix."},{"id":"cli/linter/rules/package-same-swift-prefix::bad::2","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/foo.proto","content":"Bad ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::3","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad option swift_prefix = \"Foo\"; ```","content":"Bad option swift_prefix = \"Foo\"; ```"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::4","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad ```proto // File: pkg/bar.proto","content":"Bad ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::bad::5","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#bad","headings":["Bad"],"excerpt":"Bad option swift_prefix = \"Bar\"; ```","content":"Bad option swift_prefix = \"Bar\"; ```"},{"id":"cli/linter/rules/package-same-swift-prefix::good::6","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/foo.proto","content":"Good ```proto // File: pkg/foo.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::good::7","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good option swift_prefix = \"Foo\"; // [!code focus] ```","content":"Good option swift_prefix = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-same-swift-prefix::good::8","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good ```proto // File: pkg/bar.proto","content":"Good ```proto // File: pkg/bar.proto"},{"id":"cli/linter/rules/package-same-swift-prefix::good::9","title":"PACKAGE_SAME_SWIFT_PREFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-same-swift-prefix#good","headings":["Good"],"excerpt":"Good option swift_prefix = \"Foo\"; // [!code focus] ```","content":"Good option swift_prefix = \"Foo\"; // [!code focus] ```"},{"id":"cli/linter/rules/package-version-suffix::top::0","title":"PACKAGE_VERSION_SUFFIX","path":"/docs/guide/cli/linter/rules/package-version-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/package-version-suffix::top::1","title":"PACKAGE_VERSION_SUFFIX","path":"/docs/guide/cli/linter/rules/package-version-suffix","headings":[],"excerpt":"This rule checks that the package version suffix is _vX where X is a number of version.","content":"This rule checks that the package version suffix is _vX where X is a number of version."},{"id":"cli/linter/rules/package-version-suffix::bad::2","title":"PACKAGE_VERSION_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/package-version-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-version-suffix::good::3","title":"PACKAGE_VERSION_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-version-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/package-version-suffix::good::4","title":"PACKAGE_VERSION_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/package-version-suffix#good","headings":["Good"],"excerpt":"Good package foo.v1; // [!code focus] ```","content":"Good package foo.v1; // [!code focus] ```"},{"id":"cli/linter/rules/rpc-no-client-streaming::top::0","title":"RPC_NO_CLIENT_STREAMING","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming","headings":[],"excerpt":"This rule checks that rpc has no client streaming.","content":"This rule checks that rpc has no client streaming."},{"id":"cli/linter/rules/rpc-no-client-streaming::bad::1","title":"RPC_NO_CLIENT_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-client-streaming::bad::2","title":"RPC_NO_CLIENT_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (stream BarRequest) returns (BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (stream BarRequest) returns (BarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-no-client-streaming::good::3","title":"RPC_NO_CLIENT_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-client-streaming::good::4","title":"RPC_NO_CLIENT_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-client-streaming#good","headings":["Good"],"excerpt":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-no-server-streaming::top::0","title":"RPC_NO_SERVER_STREAMING","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming","headings":[],"excerpt":"This rule checks that rpc has no server streaming.","content":"This rule checks that rpc has no server streaming."},{"id":"cli/linter/rules/rpc-no-server-streaming::bad::1","title":"RPC_NO_SERVER_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-server-streaming::bad::2","title":"RPC_NO_SERVER_STREAMING","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar (BarRequest) returns (stream BarResponse) {} } ```","content":"Bad service Foo { rpc Bar (BarRequest) returns (stream BarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-no-server-streaming::good::3","title":"RPC_NO_SERVER_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-no-server-streaming::good::4","title":"RPC_NO_SERVER_STREAMING","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-no-server-streaming#good","headings":["Good"],"excerpt":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc Bar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-pascal-case::top::0","title":"RPC_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/rpc-pascal-case","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-pascal-case::top::1","title":"RPC_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/rpc-pascal-case","headings":[],"excerpt":"This rule checks that all RPC names are in PascalCase.","content":"This rule checks that all RPC names are in PascalCase."},{"id":"cli/linter/rules/rpc-pascal-case::bad::2","title":"RPC_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-pascal-case::bad::3","title":"RPC_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#bad","headings":["Bad"],"excerpt":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/rpc-pascal-case::good::4","title":"RPC_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-pascal-case::good::5","title":"RPC_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-pascal-case#good","headings":["Good"],"excerpt":"Good service FooBar { rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] } ```","content":"Good service FooBar { rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-request-response-unique::top::0","title":"RPC_REQUEST_RESPONSE_UNIQUE","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-request-response-unique::top::1","title":"RPC_REQUEST_RESPONSE_UNIQUE","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique","headings":[],"excerpt":"This rule checks that all RPC request and response messages are unique.","content":"This rule checks that all RPC request and response messages are unique."},{"id":"cli/linter/rules/rpc-request-response-unique::bad::2","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-response-unique::bad::3","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} rpc GetBar (FooRequest) returns (FooResponse) {} } ```","content":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} rpc GetBar (FooRequest) returns (FooResponse) {} } ```"},{"id":"cli/linter/rules/rpc-request-response-unique::good::4","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-response-unique::good::5","title":"RPC_REQUEST_RESPONSE_UNIQUE","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-response-unique#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} // [!code focus] rpc GetBar (BarRequest) returns (BarResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-request-standard-name::top::0","title":"RPC_REQUEST_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-request-standard-name::top::1","title":"RPC_REQUEST_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name","headings":[],"excerpt":"This rule checks that all RPC request messages are named MethodRequest.","content":"This rule checks that all RPC request messages are named MethodRequest."},{"id":"cli/linter/rules/rpc-request-standard-name::bad::2","title":"RPC_REQUEST_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-standard-name::bad::3","title":"RPC_REQUEST_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} } ```","content":"Bad service Foo { rpc GetFoo (FooRequest) returns (FooResponse) {} } ```"},{"id":"cli/linter/rules/rpc-request-standard-name::good::4","title":"RPC_REQUEST_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-request-standard-name::good::5","title":"RPC_REQUEST_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-request-standard-name#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (GetFooRequest) returns (FooResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/rpc-response-standard-name::top::0","title":"RPC_RESPONSE_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/rpc-response-standard-name::top::1","title":"RPC_RESPONSE_STANDARD_NAME","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name","headings":[],"excerpt":"This rule checks that all RPC response messages are named MethodResponse.","content":"This rule checks that all RPC response messages are named MethodResponse."},{"id":"cli/linter/rules/rpc-response-standard-name::bad::2","title":"RPC_RESPONSE_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-response-standard-name::bad::3","title":"RPC_RESPONSE_STANDARD_NAME","section":"Bad","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc GetFoo (GetFooRequest) returns (Foo) {} } ```","content":"Bad service Foo { rpc GetFoo (GetFooRequest) returns (Foo) {} } ```"},{"id":"cli/linter/rules/rpc-response-standard-name::good::4","title":"RPC_RESPONSE_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/rpc-response-standard-name::good::5","title":"RPC_RESPONSE_STANDARD_NAME","section":"Good","path":"/docs/guide/cli/linter/rules/rpc-response-standard-name#good","headings":["Good"],"excerpt":"Good service Foo { rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] } ```","content":"Good service Foo { rpc GetFoo (GetFooRequest) returns (GetFooResponse) {} // [!code focus] } ```"},{"id":"cli/linter/rules/service-pascal-case::top::0","title":"SERVICE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/service-pascal-case","headings":[],"excerpt":"Categories: **MINIMAL** **BASIC** **DEFAULT**","content":"Categories: **MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/service-pascal-case::top::1","title":"SERVICE_PASCAL_CASE","path":"/docs/guide/cli/linter/rules/service-pascal-case","headings":[],"excerpt":"This rule checks that all service names are in PascalCase.","content":"This rule checks that all service names are in PascalCase."},{"id":"cli/linter/rules/service-pascal-case::bad::2","title":"SERVICE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/service-pascal-case#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-pascal-case::bad::3","title":"SERVICE_PASCAL_CASE","section":"Bad","path":"/docs/guide/cli/linter/rules/service-pascal-case#bad","headings":["Bad"],"excerpt":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Bad service foo_bar { rpc get_foo_bar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/service-pascal-case::good::4","title":"SERVICE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/service-pascal-case#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-pascal-case::good::5","title":"SERVICE_PASCAL_CASE","section":"Good","path":"/docs/guide/cli/linter/rules/service-pascal-case#good","headings":["Good"],"excerpt":"Good service FooBar { // [!code focus] rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} } ```","content":"Good service FooBar { // [!code focus] rpc GetFooBar (FooBarRequest) returns (FooBarResponse) {} } ```"},{"id":"cli/linter/rules/service-suffix::top::0","title":"SERVICE_SUFFIX","path":"/docs/guide/cli/linter/rules/service-suffix","headings":[],"excerpt":"**MINIMAL** **BASIC** **DEFAULT**","content":"**MINIMAL** **BASIC** **DEFAULT**"},{"id":"cli/linter/rules/service-suffix::top::1","title":"SERVICE_SUFFIX","path":"/docs/guide/cli/linter/rules/service-suffix","headings":[],"excerpt":"This rule checks that all services are suffixed with Service or your custom suffix.","content":"This rule checks that all services are suffixed with Service or your custom suffix."},{"id":"cli/linter/rules/service-suffix::bad::2","title":"SERVICE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/service-suffix#bad","headings":["Bad"],"excerpt":"Bad ```proto syntax = \"proto3\";","content":"Bad ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-suffix::bad::3","title":"SERVICE_SUFFIX","section":"Bad","path":"/docs/guide/cli/linter/rules/service-suffix#bad","headings":["Bad"],"excerpt":"Bad service Foo { rpc Bar(BarRequest) returns (BarResponse); } ```","content":"Bad service Foo { rpc Bar(BarRequest) returns (BarResponse); } ```"},{"id":"cli/linter/rules/service-suffix::good::4","title":"SERVICE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/service-suffix#good","headings":["Good"],"excerpt":"Good ```proto syntax = \"proto3\";","content":"Good ```proto syntax = \"proto3\";"},{"id":"cli/linter/rules/service-suffix::good::5","title":"SERVICE_SUFFIX","section":"Good","path":"/docs/guide/cli/linter/rules/service-suffix#good","headings":["Good"],"excerpt":"Good service FooService { // [!code focus] rpc Bar(BarRequest) returns (BarResponse); } ```","content":"Good service FooService { // [!code focus] rpc Bar(BarRequest) returns (BarResponse); } ```"},{"id":"cli/package-manager/easyp-vs-buf::top::0","title":"EasyP vs Buf Package Management","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"EasyP vs Buf Package Management","content":"EasyP vs Buf Package Management"},{"id":"cli/package-manager/easyp-vs-buf::top::1","title":"EasyP vs Buf Package Management","path":"/docs/guide/cli/package-manager/easyp-vs-buf","headings":[],"excerpt":"This document provides a comprehensive comparison between EasyP's decentralized package management approach and Buf's centralized Buf Schema Registry (BSR) model, helping you understand the key differences and choose the","content":"This document provides a comprehensive comparison between EasyP's decentralized package management approach and Buf's centralized Buf Schema Registry (BSR) model, helping you understand the key differences and choose the right solution for your needs."},{"id":"cli/package-manager/easyp-vs-buf::easyp-decentralized-git-based-approach::2","title":"EasyP vs Buf Package Management","section":"EasyP: Decentralized Git-Based Approach","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-decentralized-git-based-approach","headings":["EasyP: Decentralized Git-Based Approach"],"excerpt":"EasyP: Decentralized Git-Based Approach","content":"EasyP: Decentralized Git-Based Approach"},{"id":"cli/package-manager/easyp-vs-buf::buf-centralized-registry-approach::3","title":"EasyP vs Buf Package Management","section":"Buf: Centralized Registry Approach","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-centralized-registry-approach","headings":["Buf: Centralized Registry Approach"],"excerpt":"Buf: Centralized Registry Approach","content":"Buf: Centralized Registry Approach"},{"id":"cli/package-manager/easyp-vs-buf::key-differences-summary::4","title":"EasyP vs Buf Package Management","section":"Key Differences Summary","path":"/docs/guide/cli/package-manager/easyp-vs-buf#key-differences-summary","headings":["Key Differences Summary"],"excerpt":"Key Differences Summary Aspect EasyP Buf -------- ------- ----- **Architecture** Decentralized (Git-based) Centralized (BSR registry) **Dependency Source** Any Git repository Buf Schema Registry only **Single Point of Fa","content":"Key Differences Summary Aspect EasyP Buf -------- ------- ----- **Architecture** Decentralized (Git-based) Centralized (BSR registry) **Dependency Source** Any Git repository Buf Schema Registry only **Single Point of Failure** No Yes (buf.build) **Enterprise Deployment** Fully air-gapped support Requires BSR access or private BSR **Authentication** Git credentials (SSH/HTTPS) Buf tokens + Git credentials **Vendor Lock-in** None Buf ecosystem **Private Repositories** Native Git support Must publish to BSR first **Offline Support** Full (via vendoring) Limited (cached modules only) **Cost** Free (uses existing Git) Free tier + paid plans **Setup Complexity** Minimal Moderate (BSR setup)"},{"id":"cli/package-manager/easyp-vs-buf::1-dependency-management-philosophy::5","title":"EasyP vs Buf Package Management","section":"1. Dependency Management Philosophy","path":"/docs/guide/cli/package-manager/easyp-vs-buf#1-dependency-management-philosophy","headings":["1. Dependency Management Philosophy"],"excerpt":"Dependency Management Philosophy","content":"Dependency Management Philosophy"},{"id":"cli/package-manager/easyp-vs-buf::easyp-any-git-repository-is-a-package::6","title":"EasyP vs Buf Package Management","section":"EasyP: \"Any Git Repository is a Package\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-any-git-repository-is-a-package","headings":["EasyP: \"Any Git Repository is a Package\""],"excerpt":"EasyP: \"Any Git Repository is a Package\"","content":"EasyP: \"Any Git Repository is a Package\""},{"id":"cli/package-manager/easyp-vs-buf::easyp-any-git-repository-is-a-package::7","title":"EasyP vs Buf Package Management","section":"EasyP: \"Any Git Repository is a Package\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-any-git-repository-is-a-package","headings":["EasyP: \"Any Git Repository is a Package\""],"excerpt":"EasyP: \"Any Git Repository is a Package\" **Advantages:** ✅ Use any existing Git repository immediately ✅ No need to \"publish\" to a separate registry ✅ Version control is the source of truth ✅ Works with private Git serve","content":"EasyP: \"Any Git Repository is a Package\" **Advantages:** ✅ Use any existing Git repository immediately ✅ No need to \"publish\" to a separate registry ✅ Version control is the source of truth ✅ Works with private Git servers out-of-the-box"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::8","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\"","content":"Buf: \"Registry-First Approach\""},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::9","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\" **Advantages:** ✅ Curated, high-quality modules ✅ Rich metadata and documentation ✅ Dependency graph visualization ✅ Semantic versioning enforcement","content":"Buf: \"Registry-First Approach\" **Advantages:** ✅ Curated, high-quality modules ✅ Rich metadata and documentation ✅ Dependency graph visualization ✅ Semantic versioning enforcement"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-first-approach::10","title":"EasyP vs Buf Package Management","section":"Buf: \"Registry-First Approach\"","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-first-approach","headings":["Buf: \"Registry-First Approach\""],"excerpt":"Buf: \"Registry-First Approach\" **Limitations:** ❌ Must publish to BSR before use ❌ Requires BSR account and authentication ❌ Cannot reference arbitrary Git repositories directly","content":"Buf: \"Registry-First Approach\" **Limitations:** ❌ Must publish to BSR before use ❌ Requires BSR account and authentication ❌ Cannot reference arbitrary Git repositories directly"},{"id":"cli/package-manager/easyp-vs-buf::2-enterprise-and-air-gapped-environments::11","title":"EasyP vs Buf Package Management","section":"2. Enterprise and Air-Gapped Environments","path":"/docs/guide/cli/package-manager/easyp-vs-buf#2-enterprise-and-air-gapped-environments","headings":["2. Enterprise and Air-Gapped Environments"],"excerpt":"Enterprise and Air-Gapped Environments","content":"Enterprise and Air-Gapped Environments"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::12","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support **Scenario**: Large enterprise with strict network policies","content":"EasyP: Full Air-Gap Support **Scenario**: Large enterprise with strict network policies"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::13","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support ```bash Initial setup (with internet) easyp mod download # Downloads to ~/.easyp/ easyp mod vendor # Creates easyp_vendor/","content":"EasyP: Full Air-Gap Support ```bash Initial setup (with internet) easyp mod download # Downloads to ~/.easyp/ easyp mod vendor # Creates easyp_vendor/"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::14","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support Transfer to air-gapped environment tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... transfer archive ...","content":"EasyP: Full Air-Gap Support Transfer to air-gapped environment tar -czf easyp-deps.tar.gz ~/.easyp easyp_vendor/ ... transfer archive ..."},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::15","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support Air-gapped environment (no internet) tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Works offline ```","content":"EasyP: Full Air-Gap Support Air-gapped environment (no internet) tar -xzf easyp-deps.tar.gz export EASYPPATH=$PWD/.easyp easyp generate # Works offline ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp-full-air-gap-support::16","title":"EasyP vs Buf Package Management","section":"EasyP: Full Air-Gap Support","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-full-air-gap-support","headings":["EasyP: Full Air-Gap Support"],"excerpt":"EasyP: Full Air-Gap Support **Benefits:** ✅ Complete independence from external services ✅ No need for internal registry infrastructure ✅ Uses existing Git infrastructure ✅ Simple file-based distribution","content":"EasyP: Full Air-Gap Support **Benefits:** ✅ Complete independence from external services ✅ No need for internal registry infrastructure ✅ Uses existing Git infrastructure ✅ Simple file-based distribution"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::17","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure **Scenario**: Same enterprise setup","content":"Buf: Requires BSR Infrastructure **Scenario**: Same enterprise setup"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::18","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure ```bash Option 1: Use buf.build (requires internet) buf mod download # Must reach buf.build","content":"Buf: Requires BSR Infrastructure ```bash Option 1: Use buf.build (requires internet) buf mod download # Must reach buf.build"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::19","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure Option 2: Set up private BSR (complex) Deploy BSR server infrastructure Migrate all modules to private BSR Configure authentication and access Maintain registry server ```","content":"Buf: Requires BSR Infrastructure Option 2: Set up private BSR (complex) Deploy BSR server infrastructure Migrate all modules to private BSR Configure authentication and access Maintain registry server ```"},{"id":"cli/package-manager/easyp-vs-buf::buf-requires-bsr-infrastructure::20","title":"EasyP vs Buf Package Management","section":"Buf: Requires BSR Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-requires-bsr-infrastructure","headings":["Buf: Requires BSR Infrastructure"],"excerpt":"Buf: Requires BSR Infrastructure **Challenges:** ❌ Requires constant internet access OR expensive private BSR ❌ Complex infrastructure for private deployments ❌ All modules must be re-published to private registry ❌ Addi","content":"Buf: Requires BSR Infrastructure **Challenges:** ❌ Requires constant internet access OR expensive private BSR ❌ Complex infrastructure for private deployments ❌ All modules must be re-published to private registry ❌ Additional operational overhead"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::21","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control ```yaml Full control over dependency sources deps: # Public repository - your choice of version - github.com/googleapis/googleapis@common-protos-1_3_1","content":"EasyP: Direct Control ```yaml Full control over dependency sources deps: # Public repository - your choice of version - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::22","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control Internal repository - complete control - gitlab.company.com/security/validated-protos@v1.0.0","content":"EasyP: Direct Control Internal repository - complete control - gitlab.company.com/security/validated-protos@v1.0.0"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::23","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control Specific commit for security fix - github.com/bufbuild/protoc-gen-validate@abc123def456 ```","content":"EasyP: Direct Control Specific commit for security fix - github.com/bufbuild/protoc-gen-validate@abc123def456 ```"},{"id":"cli/package-manager/easyp-vs-buf::easyp-direct-control::24","title":"EasyP vs Buf Package Management","section":"EasyP: Direct Control","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-direct-control","headings":["EasyP: Direct Control"],"excerpt":"EasyP: Direct Control **Security advantages:** ✅ **No intermediary** - direct from source repository ✅ **Audit trail** - Git commit history is the source of truth ✅ **Cannot be \"banned\"** - no external party can revoke a","content":"EasyP: Direct Control **Security advantages:** ✅ **No intermediary** - direct from source repository ✅ **Audit trail** - Git commit history is the source of truth ✅ **Cannot be \"banned\"** - no external party can revoke access ✅ **Custom validation** - implement your own security scanning ✅ **Fork protection** - easily fork and maintain dependencies"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-dependency::25","title":"EasyP vs Buf Package Management","section":"Buf: Registry Dependency","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-dependency","headings":["Buf: Registry Dependency"],"excerpt":"Buf: Registry Dependency **Security considerations:** ⚠️ **Intermediary risk** - BSR controls what's available ⚠️ **Account suspension** - Could lose access to dependencies ⚠️ **Module removal** - Modules can be deleted ","content":"Buf: Registry Dependency **Security considerations:** ⚠️ **Intermediary risk** - BSR controls what's available ⚠️ **Account suspension** - Could lose access to dependencies ⚠️ **Module removal** - Modules can be deleted from registry ⚠️ **Update policies** - BSR may force updates or deprecations ⚠️ **Third-party trust** - Must trust Buf's security practices"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::26","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **EasyP Approach:**","content":"Scenario 1: Startup with Public Dependencies **EasyP Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::27","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **Buf Approach:**","content":"Scenario 1: Startup with Public Dependencies **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-1-startup-with-public-dependencies::28","title":"EasyP vs Buf Package Management","section":"Scenario 1: Startup with Public Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-1-startup-with-public-dependencies","headings":["Scenario 1: Startup with Public Dependencies"],"excerpt":"Scenario 1: Startup with Public Dependencies **Winner**: Tie - both work well for public dependencies","content":"Scenario 1: Startup with Public Dependencies **Winner**: Tie - both work well for public dependencies"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::29","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **EasyP Approach:** ```yaml deps: # Public - github.com/googleapis/googleapis@v1.2.3","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **EasyP Approach:** ```yaml deps: # Public - github.com/googleapis/googleapis@v1.2.3"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::30","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies Private (existing Git repos) - github.com/mycompany/auth-protos@v2.0.0 - gitlab.enterprise.com/platform/shared-types@v1.5.1 ```","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies Private (existing Git repos) - github.com/mycompany/auth-protos@v2.0.0 - gitlab.enterprise.com/platform/shared-types@v1.5.1 ```"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::31","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Buf Approach:**","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-2-enterprise-with-mixed-publicprivate-dependencies::32","title":"EasyP vs Buf Package Management","section":"Scenario 2: Enterprise with Mixed Public/Private Dependencies","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-2-enterprise-with-mixed-publicprivate-dependencies","headings":["Scenario 2: Enterprise with Mixed Public/Private Dependencies"],"excerpt":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Winner**: **EasyP** - no additional setup for private repos","content":"Scenario 2: Enterprise with Mixed Public/Private Dependencies **Winner**: **EasyP** - no additional setup for private repos"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::33","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **EasyP Approach:** ```bash Internet-connected environment easyp mod vendor","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **EasyP Approach:** ```bash Internet-connected environment easyp mod vendor"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::34","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) Transfer to classified environment Works immediately without any external dependencies ```","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) Transfer to classified environment Works immediately without any external dependencies ```"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::35","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Buf Approach:**","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Buf Approach:**"},{"id":"cli/package-manager/easyp-vs-buf::scenario-3-governmentdefense-contractor-air-gapped::36","title":"EasyP vs Buf Package Management","section":"Scenario 3: Government/Defense Contractor (Air-Gapped)","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-3-governmentdefense-contractor-air-gapped","headings":["Scenario 3: Government/Defense Contractor (Air-Gapped)"],"excerpt":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Winner**: **EasyP** - significantly simpler air-gap deployment","content":"Scenario 3: Government/Defense Contractor (Air-Gapped) **Winner**: **EasyP** - significantly simpler air-gap deployment"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::37","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **EasyP Approach:** ✅ **Direct audit trail**: Git commits show exact changes ✅ **Compliance-friendly**: No external dependencies in production ✅ **Reproducible**: Lock files pin exact ","content":"Scenario 4: Compliance and Auditing **EasyP Approach:** ✅ **Direct audit trail**: Git commits show exact changes ✅ **Compliance-friendly**: No external dependencies in production ✅ **Reproducible**: Lock files pin exact Git commits ✅ **Vulnerability management**: Direct control over security updates"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::38","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **Buf Approach:** ⚠️ **Registry dependency**: Must audit BSR's security practices ⚠️ **Third-party risk**: BSR is part of your compliance scope ⚠️ **Limited control**: Cannot control w","content":"Scenario 4: Compliance and Auditing **Buf Approach:** ⚠️ **Registry dependency**: Must audit BSR's security practices ⚠️ **Third-party risk**: BSR is part of your compliance scope ⚠️ **Limited control**: Cannot control when modules are updated/removed ⚠️ **Audit complexity**: Must trace registry → Git → actual code"},{"id":"cli/package-manager/easyp-vs-buf::scenario-4-compliance-and-auditing::39","title":"EasyP vs Buf Package Management","section":"Scenario 4: Compliance and Auditing","path":"/docs/guide/cli/package-manager/easyp-vs-buf#scenario-4-compliance-and-auditing","headings":["Scenario 4: Compliance and Auditing"],"excerpt":"Scenario 4: Compliance and Auditing **Winner**: **EasyP** - cleaner compliance story","content":"Scenario 4: Compliance and Auditing **Winner**: **EasyP** - cleaner compliance story"},{"id":"cli/package-manager/easyp-vs-buf::easyp-zero-additional-infrastructure::40","title":"EasyP vs Buf Package Management","section":"EasyP: Zero Additional Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-zero-additional-infrastructure","headings":["EasyP: Zero Additional Infrastructure"],"excerpt":"EasyP: Zero Additional Infrastructure **Costs:** ✅ **$0** - Uses existing Git infrastructure ✅ **No additional servers** to maintain ✅ **No licensing fees** for registry software ✅ **Scales with Git** - proven enterprise","content":"EasyP: Zero Additional Infrastructure **Costs:** ✅ **$0** - Uses existing Git infrastructure ✅ **No additional servers** to maintain ✅ **No licensing fees** for registry software ✅ **Scales with Git** - proven enterprise scalability"},{"id":"cli/package-manager/easyp-vs-buf::easyp-zero-additional-infrastructure::41","title":"EasyP vs Buf Package Management","section":"EasyP: Zero Additional Infrastructure","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-zero-additional-infrastructure","headings":["EasyP: Zero Additional Infrastructure"],"excerpt":"EasyP: Zero Additional Infrastructure **Infrastructure:** Uses existing Git repositories (GitHub, GitLab, etc.) Leverages existing authentication systems No additional backup/disaster recovery needed","content":"EasyP: Zero Additional Infrastructure **Infrastructure:** Uses existing Git repositories (GitHub, GitLab, etc.) Leverages existing authentication systems No additional backup/disaster recovery needed"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-infrastructure-costs::42","title":"EasyP vs Buf Package Management","section":"Buf: Registry Infrastructure Costs","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-infrastructure-costs","headings":["Buf: Registry Infrastructure Costs"],"excerpt":"Buf: Registry Infrastructure Costs **BSR Hosted (buf.build):** ✅ Free tier available ❌ Paid plans for private modules and teams ❌ Subject to external pricing changes ❌ Data locality concerns for some enterprises","content":"Buf: Registry Infrastructure Costs **BSR Hosted (buf.build):** ✅ Free tier available ❌ Paid plans for private modules and teams ❌ Subject to external pricing changes ❌ Data locality concerns for some enterprises"},{"id":"cli/package-manager/easyp-vs-buf::buf-registry-infrastructure-costs::43","title":"EasyP vs Buf Package Management","section":"Buf: Registry Infrastructure Costs","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-registry-infrastructure-costs","headings":["Buf: Registry Infrastructure Costs"],"excerpt":"Buf: Registry Infrastructure Costs **Private BSR Deployment:** ❌ Significant infrastructure costs (servers, databases, load balancers) ❌ Operational overhead (monitoring, updates, backups) ❌ Licensing costs for enterpris","content":"Buf: Registry Infrastructure Costs **Private BSR Deployment:** ❌ Significant infrastructure costs (servers, databases, load balancers) ❌ Operational overhead (monitoring, updates, backups) ❌ Licensing costs for enterprise features ❌ Additional disaster recovery planning"},{"id":"cli/package-manager/easyp-vs-buf::easyp-no-lock-in::44","title":"EasyP vs Buf Package Management","section":"EasyP: No Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-no-lock-in","headings":["EasyP: No Lock-in"],"excerpt":"EasyP: No Lock-in **Migration FROM EasyP:**","content":"EasyP: No Lock-in **Migration FROM EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::easyp-no-lock-in::45","title":"EasyP vs Buf Package Management","section":"EasyP: No Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#easyp-no-lock-in","headings":["EasyP: No Lock-in"],"excerpt":"EasyP: No Lock-in **Migration TO EasyP:**","content":"EasyP: No Lock-in **Migration TO EasyP:**"},{"id":"cli/package-manager/easyp-vs-buf::buf-potential-lock-in::46","title":"EasyP vs Buf Package Management","section":"Buf: Potential Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-potential-lock-in","headings":["Buf: Potential Lock-in"],"excerpt":"Buf: Potential Lock-in **Migration FROM Buf:** ❌ Must identify original Git repositories for each BSR module ❌ BSR-specific module names don't translate directly ❌ May lose version history and metadata ❌ Complex if heavi","content":"Buf: Potential Lock-in **Migration FROM Buf:** ❌ Must identify original Git repositories for each BSR module ❌ BSR-specific module names don't translate directly ❌ May lose version history and metadata ❌ Complex if heavily integrated with BSR ecosystem"},{"id":"cli/package-manager/easyp-vs-buf::buf-potential-lock-in::47","title":"EasyP vs Buf Package Management","section":"Buf: Potential Lock-in","path":"/docs/guide/cli/package-manager/easyp-vs-buf#buf-potential-lock-in","headings":["Buf: Potential Lock-in"],"excerpt":"Buf: Potential Lock-in **Migration TO Buf:** ❌ Must publish all dependencies to BSR first ❌ Cannot reference Git repositories directly ❌ Must adopt BSR workflow and tooling","content":"Buf: Potential Lock-in **Migration TO Buf:** ❌ Must publish all dependencies to BSR first ❌ Cannot reference Git repositories directly ❌ Must adopt BSR workflow and tooling"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::48","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Enterprise/Air-gapped environments** Need to work without external dependencies Strict compliance requirements Air-gapped or classified networks","content":"Choose EasyP When: ✅ **Enterprise/Air-gapped environments** Need to work without external dependencies Strict compliance requirements Air-gapped or classified networks"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::49","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Security-first organizations** Want direct control over dependency sources Need to audit entire supply chain Concerned about third-party service risks","content":"Choose EasyP When: ✅ **Security-first organizations** Want direct control over dependency sources Need to audit entire supply chain Concerned about third-party service risks"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::50","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Existing Git-heavy workflows** Team already comfortable with Git Extensive private repository usage Want to minimize new tools/infrastructure","content":"Choose EasyP When: ✅ **Existing Git-heavy workflows** Team already comfortable with Git Extensive private repository usage Want to minimize new tools/infrastructure"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::51","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Cost-sensitive projects** Want to avoid additional licensing costs Don't want infrastructure overhead Need predictable, zero-cost scaling","content":"Choose EasyP When: ✅ **Cost-sensitive projects** Want to avoid additional licensing costs Don't want infrastructure overhead Need predictable, zero-cost scaling"},{"id":"cli/package-manager/easyp-vs-buf::choose-easyp-when::52","title":"EasyP vs Buf Package Management","section":"Choose EasyP When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-easyp-when","headings":["Choose EasyP When:"],"excerpt":"Choose EasyP When: ✅ **Mixed public/private dependencies** Heavy use of internal Git repositories Don't want to republish existing repos Need flexibility in dependency sources","content":"Choose EasyP When: ✅ **Mixed public/private dependencies** Heavy use of internal Git repositories Don't want to republish existing repos Need flexibility in dependency sources"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::53","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Heavy BSR ecosystem usage** Already invested in Buf tooling (lint, breaking changes, generation) Want curated, high-quality modules Benefit from BSR's rich metadata and docs","content":"Choose Buf When: ✅ **Heavy BSR ecosystem usage** Already invested in Buf tooling (lint, breaking changes, generation) Want curated, high-quality modules Benefit from BSR's rich metadata and docs"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::54","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Collaborative development** Need dependency graph visualization Want centralized module discovery Benefit from BSR's collaboration features","content":"Choose Buf When: ✅ **Collaborative development** Need dependency graph visualization Want centralized module discovery Benefit from BSR's collaboration features"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::55","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Simple public-only dependencies** Primarily use well-known public modules Don't mind BSR dependency Value the curated module experience","content":"Choose Buf When: ✅ **Simple public-only dependencies** Primarily use well-known public modules Don't mind BSR dependency Value the curated module experience"},{"id":"cli/package-manager/easyp-vs-buf::choose-buf-when::56","title":"EasyP vs Buf Package Management","section":"Choose Buf When:","path":"/docs/guide/cli/package-manager/easyp-vs-buf#choose-buf-when","headings":["Choose Buf When:"],"excerpt":"Choose Buf When: ✅ **Team new to protobuf** Benefit from BSR's documentation and examples Want guided module discovery Prefer opinionated, structured approach","content":"Choose Buf When: ✅ **Team new to protobuf** Benefit from BSR's documentation and examples Want guided module discovery Prefer opinionated, structured approach"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::57","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP **Identify source repositories** for each BSR module **Map BSR modules** to Git repository references **Update configuration** to use Git URLs **Test compatibility** and resolve any issues","content":"Migrating from Buf to EasyP **Identify source repositories** for each BSR module **Map BSR modules** to Git repository references **Update configuration** to use Git URLs **Test compatibility** and resolve any issues"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::58","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP Example migration: ```yaml Before (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc","content":"Migrating from Buf to EasyP Example migration: ```yaml Before (buf.yaml) deps: - buf.build/googleapis/googleapis - buf.build/grpc/grpc"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-buf-to-easyp::59","title":"EasyP vs Buf Package Management","section":"Migrating from Buf to EasyP","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-buf-to-easyp","headings":["Migrating from Buf to EasyP"],"excerpt":"Migrating from Buf to EasyP After (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```","content":"Migrating from Buf to EasyP After (easyp.yaml) deps: - github.com/googleapis/googleapis@common-protos-1_3_1 - github.com/grpc/grpc@v1.50.0 ```"},{"id":"cli/package-manager/easyp-vs-buf::migrating-from-easyp-to-buf::60","title":"EasyP vs Buf Package Management","section":"Migrating from EasyP to Buf","path":"/docs/guide/cli/package-manager/easyp-vs-buf#migrating-from-easyp-to-buf","headings":["Migrating from EasyP to Buf"],"excerpt":"Migrating from EasyP to Buf **Publish modules** to BSR (if not already available) **Create BSR account** and configure authentication **Update configuration** to reference BSR modules **Adopt BSR workflow** (push, pull, ","content":"Migrating from EasyP to Buf **Publish modules** to BSR (if not already available) **Create BSR account** and configure authentication **Update configuration** to reference BSR modules **Adopt BSR workflow** (push, pull, etc.)"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::61","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion Both EasyP and Buf offer valid approaches to protobuf dependency management, but they serve different needs:","content":"Conclusion Both EasyP and Buf offer valid approaches to protobuf dependency management, but they serve different needs:"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::62","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion **EasyP excels in:** Enterprise and air-gapped environments Security-conscious organizations Cost-sensitive projects Direct Git repository usage Zero-infrastructure deployments","content":"Conclusion **EasyP excels in:** Enterprise and air-gapped environments Security-conscious organizations Cost-sensitive projects Direct Git repository usage Zero-infrastructure deployments"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::63","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion **Buf excels in:** Collaborative, open-source focused teams Organizations wanting curated, high-quality modules Teams new to protobuf ecosystem Projects heavily using BSR features","content":"Conclusion **Buf excels in:** Collaborative, open-source focused teams Organizations wanting curated, high-quality modules Teams new to protobuf ecosystem Projects heavily using BSR features"},{"id":"cli/package-manager/easyp-vs-buf::conclusion::64","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion The choice between EasyP and Buf often comes down to your organization's priorities around **control vs. convenience**, **security vs. collaboration features**, and **infrastructure costs vs. managed services*","content":"Conclusion The choice between EasyP and Buf often comes down to your organization's priorities around **control vs. convenience**, **security vs. collaboration features**, and **infrastructure costs vs. managed services**."},{"id":"cli/package-manager/easyp-vs-buf::conclusion::65","title":"EasyP vs Buf Package Management","section":"Conclusion","path":"/docs/guide/cli/package-manager/easyp-vs-buf#conclusion","headings":["Conclusion"],"excerpt":"Conclusion For many enterprise environments, EasyP's decentralized, Git-native approach provides the security, control, and cost-effectiveness needed for production protobuf workflows, while Buf's centralized registry ex","content":"Conclusion For many enterprise environments, EasyP's decentralized, Git-native approach provides the security, control, and cost-effectiveness needed for production protobuf workflows, while Buf's centralized registry excels in collaborative, open-source focused development environments."},{"id":"cli/package-manager/package-manager::top::0","title":"Package Manager","path":"/docs/guide/cli/package-manager/package-manager","headings":[],"excerpt":"EasyP provides a powerful package manager for protobuf dependencies that simplifies dependency management through a decentralized, Git-based approach. Unlike centralized solutions, EasyP works directly with Git repositor","content":"EasyP provides a powerful package manager for protobuf dependencies that simplifies dependency management through a decentralized, Git-based approach. Unlike centralized solutions, EasyP works directly with Git repositories, giving you complete control over your dependencies."},{"id":"cli/package-manager/package-manager::overview::1","title":"Package Manager","section":"Overview","path":"/docs/guide/cli/package-manager/package-manager#overview","headings":["Overview"],"excerpt":"Overview The EasyP package manager follows the **Go modules philosophy** - any Git repository can serve as a package source. This approach provides several key advantages:","content":"Overview The EasyP package manager follows the **Go modules philosophy** - any Git repository can serve as a package source. This approach provides several key advantages:"},{"id":"cli/package-manager/package-manager::overview::2","title":"Package Manager","section":"Overview","path":"/docs/guide/cli/package-manager/package-manager#overview","headings":["Overview"],"excerpt":"Overview **Decentralized**: No single point of failure or control **Security**: Direct access to source repositories **Flexibility**: Support for public, private, and enterprise repositories **Reproducibility**: Lock fil","content":"Overview **Decentralized**: No single point of failure or control **Security**: Direct access to source repositories **Flexibility**: Support for public, private, and enterprise repositories **Reproducibility**: Lock files ensure consistent builds across environments **Performance**: Local caching minimizes network requests"},{"id":"cli/package-manager/package-manager::key-features::3","title":"Package Manager","section":"Key Features","path":"/docs/guide/cli/package-manager/package-manager#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- **Git-Native** Works with any Git repository - no special server required **Multiple Version Formats** Tags, commits, pseudo-versions, latest **Lock Files** Reprod","content":"Key Features Feature Description --------- ------------- **Git-Native** Works with any Git repository - no special server required **Multiple Version Formats** Tags, commits, pseudo-versions, latest **Lock Files** Reproducible builds with easyp.lock **Local Caching** Go modules-style cache architecture **Vendoring Support** Copy dependencies locally for offline builds **YAML Configuration** Simple, readable dependency declarations"},{"id":"cli/package-manager/package-manager::architecture::4","title":"Package Manager","section":"Architecture","path":"/docs/guide/cli/package-manager/package-manager#architecture","headings":["Architecture"],"excerpt":"Architecture EasyP uses a two-tier caching system inspired by Go modules:","content":"Architecture EasyP uses a two-tier caching system inspired by Go modules:"},{"id":"cli/package-manager/package-manager::cache-location::5","title":"Package Manager","section":"Cache Location","path":"/docs/guide/cli/package-manager/package-manager#cache-location","headings":["Cache Location"],"excerpt":"Cache Location Environment Location How to Set ------------- ---------- ------------ **Default** $HOME/.easyp Automatic **Custom** Any directory Set EASYPPATH environment variable **CI/CD** Project-relative export EASYPP","content":"Cache Location Environment Location How to Set ------------- ---------- ------------ **Default** $HOME/.easyp Automatic **Custom** Any directory Set EASYPPATH environment variable **CI/CD** Project-relative export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::basic-configuration::6","title":"Package Manager","section":"Basic Configuration","path":"/docs/guide/cli/package-manager/package-manager#basic-configuration","headings":["Basic Configuration"],"excerpt":"Basic Configuration Configure dependencies in your easyp.yaml file:","content":"Basic Configuration Configure dependencies in your easyp.yaml file:"},{"id":"cli/package-manager/package-manager::advanced-configuration-examples::7","title":"Package Manager","section":"Advanced Configuration Examples","path":"/docs/guide/cli/package-manager/package-manager#advanced-configuration-examples","headings":["Advanced Configuration Examples"],"excerpt":"Advanced Configuration Examples","content":"Advanced Configuration Examples"},{"id":"cli/package-manager/package-manager::multi-environment-setup::8","title":"Package Manager","section":"Multi-Environment Setup","path":"/docs/guide/cli/package-manager/package-manager#multi-environment-setup","headings":["Multi-Environment Setup"],"excerpt":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Latest for development - github.com/mycompany/internal-protos # Latest internal changes - github.com/bufbuild/protoc-gen-v","content":"Multi-Environment Setup ```yaml development.easyp.yaml deps: - github.com/googleapis/googleapis # Latest for development - github.com/mycompany/internal-protos # Latest internal changes - github.com/bufbuild/protoc-gen-validate # Latest features"},{"id":"cli/package-manager/package-manager::multi-environment-setup::9","title":"Package Manager","section":"Multi-Environment Setup","path":"/docs/guide/cli/package-manager/package-manager#multi-environment-setup","headings":["Multi-Environment Setup"],"excerpt":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Pinned - github.com/mycompany/internal-protos@v2.1.0 # Stable release - github.com/bufbuild/protoc-gen-validate","content":"Multi-Environment Setup production.easyp.yaml deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Pinned - github.com/mycompany/internal-protos@v2.1.0 # Stable release - github.com/bufbuild/protoc-gen-validate@v0.10.1 # Tested version ```"},{"id":"cli/package-manager/package-manager::private-repository-setup::10","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup ```yaml deps: # Public dependencies - github.com/googleapis/googleapis@common-protos-1_3_1","content":"Private Repository Setup ```yaml deps: # Public dependencies - github.com/googleapis/googleapis@common-protos-1_3_1"},{"id":"cli/package-manager/package-manager::private-repository-setup::11","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup Private company repositories - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1","content":"Private Repository Setup Private company repositories - github.com/mycompany/auth-protos@v1.5.0 - github.com/mycompany/common-types@v2.0.1"},{"id":"cli/package-manager/package-manager::private-repository-setup::12","title":"Package Manager","section":"Private Repository Setup","path":"/docs/guide/cli/package-manager/package-manager#private-repository-setup","headings":["Private Repository Setup"],"excerpt":"Private Repository Setup Internal GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```","content":"Private Repository Setup Internal GitLab - gitlab.company.com/platform/messaging-protos@v0.3.0 ```"},{"id":"cli/package-manager/package-manager::versioning-strategies::13","title":"Package Manager","section":"Versioning Strategies","path":"/docs/guide/cli/package-manager/package-manager#versioning-strategies","headings":["Versioning Strategies"],"excerpt":"Versioning Strategies EasyP supports multiple versioning approaches to fit different development workflows:","content":"Versioning Strategies EasyP supports multiple versioning approaches to fit different development workflows:"},{"id":"cli/package-manager/package-manager::1-semantic-version-tags-recommended-for-production::14","title":"Package Manager","section":"1. Semantic Version Tags (Recommended for Production)","path":"/docs/guide/cli/package-manager/package-manager#1-semantic-version-tags-recommended-for-production","headings":["1. Semantic Version Tags (Recommended for Production)"],"excerpt":"Semantic Version Tags (Recommended for Production)","content":"Semantic Version Tags (Recommended for Production)"},{"id":"cli/package-manager/package-manager::1-semantic-version-tags-recommended-for-production::15","title":"Package Manager","section":"1. Semantic Version Tags (Recommended for Production)","path":"/docs/guide/cli/package-manager/package-manager#1-semantic-version-tags-recommended-for-production","headings":["1. Semantic Version Tags (Recommended for Production)"],"excerpt":"Semantic Version Tags (Recommended for Production) **Use when:** Production deployments Stable API consumption Reproducible builds required","content":"Semantic Version Tags (Recommended for Production) **Use when:** Production deployments Stable API consumption Reproducible builds required"},{"id":"cli/package-manager/package-manager::2-latest-tag-development::16","title":"Package Manager","section":"2. Latest Tag (Development)","path":"/docs/guide/cli/package-manager/package-manager#2-latest-tag-development","headings":["2. Latest Tag (Development)"],"excerpt":"Latest Tag (Development) **Use when:** Active development Want latest features Compatibility testing","content":"Latest Tag (Development) **Use when:** Active development Want latest features Compatibility testing"},{"id":"cli/package-manager/package-manager::3-commit-hashes-bleeding-edge::17","title":"Package Manager","section":"3. Commit Hashes (Bleeding Edge)","path":"/docs/guide/cli/package-manager/package-manager#3-commit-hashes-bleeding-edge","headings":["3. Commit Hashes (Bleeding Edge)"],"excerpt":"Commit Hashes (Bleeding Edge) **Use when:** Need unreleased features Testing specific fixes Contributing to upstream","content":"Commit Hashes (Bleeding Edge) **Use when:** Need unreleased features Testing specific fixes Contributing to upstream"},{"id":"cli/package-manager/package-manager::4-pseudo-versions-automatic::18","title":"Package Manager","section":"4. Pseudo-Versions (Automatic)","path":"/docs/guide/cli/package-manager/package-manager#4-pseudo-versions-automatic","headings":["4. Pseudo-Versions (Automatic)"],"excerpt":"Pseudo-Versions (Automatic) When EasyP can't find a suitable tag, it generates pseudo-versions automatically:","content":"Pseudo-Versions (Automatic) When EasyP can't find a suitable tag, it generates pseudo-versions automatically:"},{"id":"cli/package-manager/package-manager::4-pseudo-versions-automatic::19","title":"Package Manager","section":"4. Pseudo-Versions (Automatic)","path":"/docs/guide/cli/package-manager/package-manager#4-pseudo-versions-automatic","headings":["4. Pseudo-Versions (Automatic)"],"excerpt":"Pseudo-Versions (Automatic) This ensures every commit can be referenced with a version-like identifier.","content":"Pseudo-Versions (Automatic) This ensures every commit can be referenced with a version-like identifier."},{"id":"cli/package-manager/package-manager::easyp-mod-download::20","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Downloads and installs all dependencies declared in your configuration.","content":"easyp mod download Downloads and installs all dependencies declared in your configuration."},{"id":"cli/package-manager/package-manager::easyp-mod-download::21","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **What happens:** **Resolves versions**: Converts tags/latest to specific commits **Downloads archives**: Stores .zip files in cache/download **Verifies checksums**: Ensures archive integrity **Extract","content":"easyp mod download **What happens:** **Resolves versions**: Converts tags/latest to specific commits **Downloads archives**: Stores .zip files in cache/download **Verifies checksums**: Ensures archive integrity **Extracts modules**: Unpacks to cache/mod with proper structure **Updates lock file**: Records exact versions and content hashes"},{"id":"cli/package-manager/package-manager::easyp-mod-download::22","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Usage:** ```bash Use default easyp.yaml easyp mod download","content":"easyp mod download **Usage:** ```bash Use default easyp.yaml easyp mod download"},{"id":"cli/package-manager/package-manager::easyp-mod-download::23","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download Use custom config file easyp --cfg production.easyp.yaml mod download","content":"easyp mod download Use custom config file easyp --cfg production.easyp.yaml mod download"},{"id":"cli/package-manager/package-manager::easyp-mod-download::24","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download With custom cache location EASYPPATH=/tmp/easyp-cache easyp mod download ```","content":"easyp mod download With custom cache location EASYPPATH=/tmp/easyp-cache easyp mod download ```"},{"id":"cli/package-manager/package-manager::easyp-mod-download::25","title":"Package Manager","section":"easyp mod download","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-download","headings":["easyp mod download"],"excerpt":"easyp mod download **Example output:**","content":"easyp mod download **Example output:**"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::26","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor Copies all installed proto files to a local easyp_vendor/ directory for offline usage.","content":"easyp mod vendor Copies all installed proto files to a local easyp_vendor/ directory for offline usage."},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::27","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Use cases:** **Docker builds**: Avoid network dependencies in containers **Air-gapped environments**: No internet access during builds **Reproducible builds**: Bundle exact dependency versions **Perfor","content":"easyp mod vendor **Use cases:** **Docker builds**: Avoid network dependencies in containers **Air-gapped environments**: No internet access during builds **Reproducible builds**: Bundle exact dependency versions **Performance**: Eliminate network latency in repeated builds"},{"id":"cli/package-manager/package-manager::easyp-mod-vendor::28","title":"Package Manager","section":"easyp mod vendor","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-vendor","headings":["easyp mod vendor"],"excerpt":"easyp mod vendor **Result structure:**","content":"easyp mod vendor **Result structure:**"},{"id":"cli/package-manager/package-manager::easyp-mod-update::29","title":"Package Manager","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update Updates module versions based on current configuration and writes resolved versions to the lock file.","content":"easyp mod update Updates module versions based on current configuration and writes resolved versions to the lock file."},{"id":"cli/package-manager/package-manager::easyp-mod-update::30","title":"Package Manager","section":"easyp mod update","path":"/docs/guide/cli/package-manager/package-manager#easyp-mod-update","headings":["easyp mod update"],"excerpt":"easyp mod update **Behavior:** Respects version constraints in easyp.yaml Updates to latest compatible versions Regenerates easyp.lock with new versions and hashes","content":"easyp mod update **Behavior:** Respects version constraints in easyp.yaml Updates to latest compatible versions Regenerates easyp.lock with new versions and hashes"},{"id":"cli/package-manager/package-manager::lock-files::31","title":"Package Manager","section":"Lock Files","path":"/docs/guide/cli/package-manager/package-manager#lock-files","headings":["Lock Files"],"excerpt":"Lock Files The easyp.lock file ensures reproducible builds by recording exact versions and content hashes:","content":"Lock Files The easyp.lock file ensures reproducible builds by recording exact versions and content hashes:"},{"id":"cli/package-manager/package-manager::lock-file-format::32","title":"Package Manager","section":"Lock File Format","path":"/docs/guide/cli/package-manager/package-manager#lock-file-format","headings":["Lock File Format"],"excerpt":"Lock File Format Each line contains three components: **Module path**: Full repository path **Exact version**: Resolved version (tag or pseudo-version) **Content hash**: SHA256 of extracted content (h1: prefix)","content":"Lock File Format Each line contains three components: **Module path**: Full repository path **Exact version**: Resolved version (tag or pseudo-version) **Content hash**: SHA256 of extracted content (h1: prefix)"},{"id":"cli/package-manager/package-manager::best-practices::33","title":"Package Manager","section":"Best Practices","path":"/docs/guide/cli/package-manager/package-manager#best-practices","headings":["Best Practices"],"excerpt":"Best Practices ✅ **Always commit easyp.lock** - Ensures team consistency ✅ **Run mod update deliberately** - Don't auto-update in CI ✅ **Review lock changes** - Understand what's being updated ❌ **Don't edit manually** -","content":"Best Practices ✅ **Always commit easyp.lock** - Ensures team consistency ✅ **Run mod update deliberately** - Don't auto-update in CI ✅ **Review lock changes** - Understand what's being updated ❌ **Don't edit manually** - Let EasyP manage the format"},{"id":"cli/package-manager/package-manager::public-repositories::34","title":"Package Manager","section":"Public Repositories","path":"/docs/guide/cli/package-manager/package-manager#public-repositories","headings":["Public Repositories"],"excerpt":"Public Repositories No setup required - works out of the box:","content":"Public Repositories No setup required - works out of the box:"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::35","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) Configure Git to use SSH for GitHub/GitLab:","content":"SSH Keys (Recommended) Configure Git to use SSH for GitHub/GitLab:"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::36","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) ```bash For GitHub git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\"","content":"SSH Keys (Recommended) ```bash For GitHub git config --global url.\"git@github.com:\".insteadOf \"https://github.com/\""},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::37","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) For GitLab git config --global url.\"git@gitlab.com:\".insteadOf \"https://gitlab.com/\"","content":"SSH Keys (Recommended) For GitLab git config --global url.\"git@gitlab.com:\".insteadOf \"https://gitlab.com/\""},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::38","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) For custom domains git config --global url.\"git@gitlab.company.com:\".insteadOf \"https://gitlab.company.com/\" ```","content":"SSH Keys (Recommended) For custom domains git config --global url.\"git@gitlab.company.com:\".insteadOf \"https://gitlab.company.com/\" ```"},{"id":"cli/package-manager/package-manager::ssh-keys-recommended::39","title":"Package Manager","section":"SSH Keys (Recommended)","path":"/docs/guide/cli/package-manager/package-manager#ssh-keys-recommended","headings":["SSH Keys (Recommended)"],"excerpt":"SSH Keys (Recommended) Then use normal HTTPS URLs in your config:","content":"SSH Keys (Recommended) Then use normal HTTPS URLs in your config:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::40","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens For HTTPS authentication:","content":"Personal Access Tokens For HTTPS authentication:"},{"id":"cli/package-manager/package-manager::personal-access-tokens::41","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens ```bash Method 1: Credential helper git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials","content":"Personal Access Tokens ```bash Method 1: Credential helper git config --global credential.helper store echo \"https://username:token@github.com\" >> ~/.git-credentials"},{"id":"cli/package-manager/package-manager::personal-access-tokens::42","title":"Package Manager","section":"Personal Access Tokens","path":"/docs/guide/cli/package-manager/package-manager#personal-access-tokens","headings":["Personal Access Tokens"],"excerpt":"Personal Access Tokens Method 2: URL rewriting git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```","content":"Personal Access Tokens Method 2: URL rewriting git config --global url.\"https://username:token@github.com/mycompany\".insteadOf \"https://github.com/mycompany\" ```"},{"id":"cli/package-manager/package-manager::corporate-environments::43","title":"Package Manager","section":"Corporate Environments","path":"/docs/guide/cli/package-manager/package-manager#corporate-environments","headings":["Corporate Environments"],"excerpt":"Corporate Environments ```bash Configure proxy git config --global http.proxy http://proxy.company.com:8080 git config --global https.proxy https://proxy.company.com:8080","content":"Corporate Environments ```bash Configure proxy git config --global http.proxy http://proxy.company.com:8080 git config --global https.proxy https://proxy.company.com:8080"},{"id":"cli/package-manager/package-manager::corporate-environments::44","title":"Package Manager","section":"Corporate Environments","path":"/docs/guide/cli/package-manager/package-manager#corporate-environments","headings":["Corporate Environments"],"excerpt":"Corporate Environments Configure certificates for internal Git servers git config --global http.sslCAInfo /path/to/certificate.pem ```","content":"Corporate Environments Configure certificates for internal Git servers git config --global http.sslCAInfo /path/to/certificate.pem ```"},{"id":"cli/package-manager/package-manager::initial-project-setup::45","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup ```bash Create configuration cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF","content":"Initial Project Setup ```bash Create configuration cat > easyp.yaml << EOF deps: - github.com/googleapis/googleapis - github.com/grpc-ecosystem/grpc-gateway@v2.19.1 EOF"},{"id":"cli/package-manager/package-manager::initial-project-setup::46","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup Download dependencies easyp mod download","content":"Initial Project Setup Download dependencies easyp mod download"},{"id":"cli/package-manager/package-manager::initial-project-setup::47","title":"Package Manager","section":"Initial Project Setup","path":"/docs/guide/cli/package-manager/package-manager#initial-project-setup","headings":["Initial Project Setup"],"excerpt":"Initial Project Setup Verify installation ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```","content":"Initial Project Setup Verify installation ls ~/.easyp/mod/github.com/googleapis/googleapis/ ```"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::48","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies ```bash Edit easyp.yaml echo \" - github.com/bufbuild/protoc-gen-validate@v0.10.1\" >> easyp.yaml","content":"Adding New Dependencies ```bash Edit easyp.yaml echo \" - github.com/bufbuild/protoc-gen-validate@v0.10.1\" >> easyp.yaml"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::49","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies Download new dependency easyp mod download","content":"Adding New Dependencies Download new dependency easyp mod download"},{"id":"cli/package-manager/package-manager::adding-new-dependencies::50","title":"Package Manager","section":"Adding New Dependencies","path":"/docs/guide/cli/package-manager/package-manager#adding-new-dependencies","headings":["Adding New Dependencies"],"excerpt":"Adding New Dependencies Commit lock file changes git add easyp.lock git commit -m \"Add protoc-gen-validate dependency\" ```","content":"Adding New Dependencies Commit lock file changes git add easyp.lock git commit -m \"Add protoc-gen-validate dependency\" ```"},{"id":"cli/package-manager/package-manager::updating-dependencies::51","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies ```bash Update to latest compatible versions easyp mod update","content":"Updating Dependencies ```bash Update to latest compatible versions easyp mod update"},{"id":"cli/package-manager/package-manager::updating-dependencies::52","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Review changes git diff easyp.lock","content":"Updating Dependencies Review changes git diff easyp.lock"},{"id":"cli/package-manager/package-manager::updating-dependencies::53","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Test with new versions easyp generate easyp lint","content":"Updating Dependencies Test with new versions easyp generate easyp lint"},{"id":"cli/package-manager/package-manager::updating-dependencies::54","title":"Package Manager","section":"Updating Dependencies","path":"/docs/guide/cli/package-manager/package-manager#updating-dependencies","headings":["Updating Dependencies"],"excerpt":"Updating Dependencies Commit if everything works git add easyp.lock git commit -m \"Update dependencies\" ```","content":"Updating Dependencies Commit if everything works git add easyp.lock git commit -m \"Update dependencies\" ```"},{"id":"cli/package-manager/package-manager::offline-development::55","title":"Package Manager","section":"Offline Development","path":"/docs/guide/cli/package-manager/package-manager#offline-development","headings":["Offline Development"],"excerpt":"Offline Development ```bash Vendor all dependencies easyp mod vendor","content":"Offline Development ```bash Vendor all dependencies easyp mod vendor"},{"id":"cli/package-manager/package-manager::offline-development::56","title":"Package Manager","section":"Offline Development","path":"/docs/guide/cli/package-manager/package-manager#offline-development","headings":["Offline Development"],"excerpt":"Offline Development Now your project works offline easyp generate ```","content":"Offline Development Now your project works offline easyp generate ```"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::57","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" **Problem**: Can't access private repository **Solution**: Check authentication setup","content":"\"Repository not found\" or \"Authentication failed\" **Problem**: Can't access private repository **Solution**: Check authentication setup"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::58","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" ```bash Test Git access git ls-remote https://github.com/mycompany/private-repo","content":"\"Repository not found\" or \"Authentication failed\" ```bash Test Git access git ls-remote https://github.com/mycompany/private-repo"},{"id":"cli/package-manager/package-manager::repository-not-found-or-authentication-failed::59","title":"Package Manager","section":"\"Repository not found\" or \"Authentication failed\"","path":"/docs/guide/cli/package-manager/package-manager#repository-not-found-or-authentication-failed","headings":["\"Repository not found\" or \"Authentication failed\""],"excerpt":"\"Repository not found\" or \"Authentication failed\" Check Git configuration git config --list grep url ```","content":"\"Repository not found\" or \"Authentication failed\" Check Git configuration git config --list grep url ```"},{"id":"cli/package-manager/package-manager::version-not-found::60","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" **Problem**: Specified tag/version doesn't exist **Solution**: Check available tags","content":"\"Version not found\" **Problem**: Specified tag/version doesn't exist **Solution**: Check available tags"},{"id":"cli/package-manager/package-manager::version-not-found::61","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" ```bash List available tags git ls-remote --tags https://github.com/googleapis/googleapis","content":"\"Version not found\" ```bash List available tags git ls-remote --tags https://github.com/googleapis/googleapis"},{"id":"cli/package-manager/package-manager::version-not-found::62","title":"Package Manager","section":"\"Version not found\"","path":"/docs/guide/cli/package-manager/package-manager#version-not-found","headings":["\"Version not found\""],"excerpt":"\"Version not found\" Use existing tag or commit hash deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Valid tag ```","content":"\"Version not found\" Use existing tag or commit hash deps: - github.com/googleapis/googleapis@common-protos-1_3_1 # Valid tag ```"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::63","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" **Problem**: Corrupted cache files **Solution**: Clear cache and re-download","content":"\"Cache corruption\" or \"Checksum mismatch\" **Problem**: Corrupted cache files **Solution**: Clear cache and re-download"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::64","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" ```bash Clear everything rm -rf ~/.easyp","content":"\"Cache corruption\" or \"Checksum mismatch\" ```bash Clear everything rm -rf ~/.easyp"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::65","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" Or clear just downloads rm -rf ~/.easyp/cache/download","content":"\"Cache corruption\" or \"Checksum mismatch\" Or clear just downloads rm -rf ~/.easyp/cache/download"},{"id":"cli/package-manager/package-manager::cache-corruption-or-checksum-mismatch::66","title":"Package Manager","section":"\"Cache corruption\" or \"Checksum mismatch\"","path":"/docs/guide/cli/package-manager/package-manager#cache-corruption-or-checksum-mismatch","headings":["\"Cache corruption\" or \"Checksum mismatch\""],"excerpt":"\"Cache corruption\" or \"Checksum mismatch\" Re-download easyp mod download ```","content":"\"Cache corruption\" or \"Checksum mismatch\" Re-download easyp mod download ```"},{"id":"cli/package-manager/package-manager::network-timeouts::67","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts **Problem**: Slow or unreliable network **Solution**: Configure Git timeouts","content":"Network timeouts **Problem**: Slow or unreliable network **Solution**: Configure Git timeouts"},{"id":"cli/package-manager/package-manager::network-timeouts::68","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts ```bash Increase timeout git config --global http.lowSpeedLimit 1000 git config --global http.lowSpeedTime 300","content":"Network timeouts ```bash Increase timeout git config --global http.lowSpeedLimit 1000 git config --global http.lowSpeedTime 300"},{"id":"cli/package-manager/package-manager::network-timeouts::69","title":"Package Manager","section":"Network timeouts","path":"/docs/guide/cli/package-manager/package-manager#network-timeouts","headings":["Network timeouts"],"excerpt":"Network timeouts Use proxy if available git config --global http.proxy http://proxy.company.com:8080 ```","content":"Network timeouts Use proxy if available git config --global http.proxy http://proxy.company.com:8080 ```"},{"id":"cli/package-manager/package-manager::for-large-teams::70","title":"Package Manager","section":"For Large Teams","path":"/docs/guide/cli/package-manager/package-manager#for-large-teams","headings":["For Large Teams"],"excerpt":"For Large Teams ```bash Use shared cache server (if available) export EASYPPATH=/shared/easyp-cache","content":"For Large Teams ```bash Use shared cache server (if available) export EASYPPATH=/shared/easyp-cache"},{"id":"cli/package-manager/package-manager::for-large-teams::71","title":"Package Manager","section":"For Large Teams","path":"/docs/guide/cli/package-manager/package-manager#for-large-teams","headings":["For Large Teams"],"excerpt":"For Large Teams Or use team-specific cache export EASYPPATH=/team-cache/easyp ```","content":"For Large Teams Or use team-specific cache export EASYPPATH=/team-cache/easyp ```"},{"id":"cli/package-manager/package-manager::for-cicd-systems::72","title":"Package Manager","section":"For CI/CD Systems","path":"/docs/guide/cli/package-manager/package-manager#for-cicd-systems","headings":["For CI/CD Systems"],"excerpt":"For CI/CD Systems ```bash Use project-relative cache export EASYPPATH=$CI_PROJECT_DIR/.easyp","content":"For CI/CD Systems ```bash Use project-relative cache export EASYPPATH=$CI_PROJECT_DIR/.easyp"},{"id":"cli/package-manager/package-manager::for-cicd-systems::73","title":"Package Manager","section":"For CI/CD Systems","path":"/docs/guide/cli/package-manager/package-manager#for-cicd-systems","headings":["For CI/CD Systems"],"excerpt":"For CI/CD Systems Cache between builds (GitLab CI example) cache: key: easyp-$CI_COMMIT_REF_SLUG paths: - .easyp/ ```","content":"For CI/CD Systems Cache between builds (GitLab CI example) cache: key: easyp-$CI_COMMIT_REF_SLUG paths: - .easyp/ ```"},{"id":"cli/package-manager/package-manager::cache-size-management::74","title":"Package Manager","section":"Cache Size Management","path":"/docs/guide/cli/package-manager/package-manager#cache-size-management","headings":["Cache Size Management"],"excerpt":"Cache Size Management ```bash Check cache usage du -sh ~/.easyp du -sh ~/.easyp/cache/download # Archives only du -sh ~/.easyp/mod # Extracted modules","content":"Cache Size Management ```bash Check cache usage du -sh ~/.easyp du -sh ~/.easyp/cache/download # Archives only du -sh ~/.easyp/mod # Extracted modules"},{"id":"cli/package-manager/package-manager::cache-size-management::75","title":"Package Manager","section":"Cache Size Management","path":"/docs/guide/cli/package-manager/package-manager#cache-size-management","headings":["Cache Size Management"],"excerpt":"Cache Size Management Clean old versions (manual) find ~/.easyp/mod -type d -name \"v0.0.0-*\" -mtime +30 -exec rm -rf {} \\; ```","content":"Cache Size Management Clean old versions (manual) find ~/.easyp/mod -type d -name \"v0.0.0-*\" -mtime +30 -exec rm -rf {} \\; ```"},{"id":"cli/package-manager/package-manager::docker-multi-stage-build::76","title":"Package Manager","section":"Docker Multi-stage Build","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage-build","headings":["Docker Multi-stage Build"],"excerpt":"Docker Multi-stage Build ```dockerfile Stage 1: Download dependencies FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor","content":"Docker Multi-stage Build ```dockerfile Stage 1: Download dependencies FROM ghcr.io/easyp-tech/easyp:latest AS deps WORKDIR /workspace COPY easyp.yaml easyp.lock ./ RUN easyp mod vendor"},{"id":"cli/package-manager/package-manager::docker-multi-stage-build::77","title":"Package Manager","section":"Docker Multi-stage Build","path":"/docs/guide/cli/package-manager/package-manager#docker-multi-stage-build","headings":["Docker Multi-stage Build"],"excerpt":"Docker Multi-stage Build Stage 2: Build application FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . Use vendored dependencies for generation RUN easyp generate ``","content":"Docker Multi-stage Build Stage 2: Build application FROM alpine:latest AS build WORKDIR /app COPY --from=deps /workspace/easyp_vendor ./easyp_vendor COPY . . Use vendored dependencies for generation RUN easyp generate ```"},{"id":"cli/package-manager/package-manager::monorepo-structure::78","title":"Package Manager","section":"Monorepo Structure","path":"/docs/guide/cli/package-manager/package-manager#monorepo-structure","headings":["Monorepo Structure"],"excerpt":"Monorepo Structure Each easyp.yaml can have different dependencies based on service needs.","content":"Monorepo Structure Each easyp.yaml can have different dependencies based on service needs."},{"id":"cli/package-manager/package-manager::development-workflow::79","title":"Package Manager","section":"Development Workflow","path":"/docs/guide/cli/package-manager/package-manager#development-workflow","headings":["Development Workflow"],"excerpt":"Development Workflow ✅ Use **latest tags** during active development ✅ **Pin versions** for production deployments ✅ **Commit lock files** to ensure reproducibility ✅ **Review dependency updates** before merging ✅ **Test","content":"Development Workflow ✅ Use **latest tags** during active development ✅ **Pin versions** for production deployments ✅ **Commit lock files** to ensure reproducibility ✅ **Review dependency updates** before merging ✅ **Test after updates** to catch compatibility issues"},{"id":"cli/package-manager/package-manager::security::80","title":"Package Manager","section":"Security","path":"/docs/guide/cli/package-manager/package-manager#security","headings":["Security"],"excerpt":"Security ✅ **Pin to specific versions** in production ✅ **Use SSH keys** for private repositories ✅ **Review new dependencies** for security implications ✅ **Monitor for vulnerabilities** in dependencies ❌ **Don't embed ","content":"Security ✅ **Pin to specific versions** in production ✅ **Use SSH keys** for private repositories ✅ **Review new dependencies** for security implications ✅ **Monitor for vulnerabilities** in dependencies ❌ **Don't embed credentials** in configuration files"},{"id":"cli/package-manager/package-manager::performance::81","title":"Package Manager","section":"Performance","path":"/docs/guide/cli/package-manager/package-manager#performance","headings":["Performance"],"excerpt":"Performance ✅ **Cache aggressively** in CI/CD systems ✅ **Use vendoring** for frequently rebuilt projects ✅ **Clean old cache** periodically to save space ✅ **Use shared cache** for team environments","content":"Performance ✅ **Cache aggressively** in CI/CD systems ✅ **Use vendoring** for frequently rebuilt projects ✅ **Clean old cache** periodically to save space ✅ **Use shared cache** for team environments"},{"id":"cli/package-manager/package-manager::team-collaboration::82","title":"Package Manager","section":"Team Collaboration","path":"/docs/guide/cli/package-manager/package-manager#team-collaboration","headings":["Team Collaboration"],"excerpt":"Team Collaboration ✅ **Document authentication setup** for new team members ✅ **Use consistent tooling** across environments ✅ **Automate dependency updates** with proper testing ✅ **Share cache locations** when possible","content":"Team Collaboration ✅ **Document authentication setup** for new team members ✅ **Use consistent tooling** across environments ✅ **Automate dependency updates** with proper testing ✅ **Share cache locations** when possible"},{"id":"cli/package-manager/package-manager::team-collaboration::83","title":"Package Manager","section":"Team Collaboration","path":"/docs/guide/cli/package-manager/package-manager#team-collaboration","headings":["Team Collaboration"],"excerpt":"Team Collaboration The EasyP package manager provides a robust, decentralized solution for protobuf dependency management that scales from individual projects to enterprise environments while maintaining the simplicity a","content":"Team Collaboration The EasyP package manager provides a robust, decentralized solution for protobuf dependency management that scales from individual projects to enterprise environments while maintaining the simplicity and reliability developers expect."},{"id":"introduction/install::install-from-systems-package-manager::0","title":"Install the EasyP cli","section":"Install from system's package manager","path":"/docs/guide/introduction/install#install-from-systems-package-manager","headings":["Install from system's package manager"],"excerpt":"Install from system's package manager","content":"Install from system's package manager"},{"id":"introduction/install::recommended-installation-method::1","title":"Install the EasyP cli","section":"Recommended installation method","path":"/docs/guide/introduction/install#recommended-installation-method","headings":["Recommended installation method"],"excerpt":"Recommended installation method","content":"Recommended installation method"},{"id":"introduction/install::homebrew::2","title":"Install the EasyP cli","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew You can install a binary release on macOS using brew:","content":"Homebrew You can install a binary release on macOS using brew:"},{"id":"introduction/install::homebrew::3","title":"Install the EasyP cli","section":"Homebrew","path":"/docs/guide/introduction/install#homebrew","headings":["Homebrew"],"excerpt":"Homebrew Work in progress apt, yum, pacman, etc.","content":"Homebrew Work in progress apt, yum, pacman, etc."},{"id":"introduction/install::_not-recommended_::4","title":"Install the EasyP cli","section":"_Not recommended_","path":"/docs/guide/introduction/install#_not-recommended_","headings":["_Not recommended_"],"excerpt":"_Not recommended_ Local installation is not recommended because package managers provide: Automatic updates and security patches Better integration with system package management Easier installation and removal process V","content":"_Not recommended_ Local installation is not recommended because package managers provide: Automatic updates and security patches Better integration with system package management Easier installation and removal process Verified and signed binaries"},{"id":"introduction/install::go-install::5","title":"Install the EasyP cli","section":"Go install","path":"/docs/guide/introduction/install#go-install","headings":["Go install"],"excerpt":"Go install It will install the latest stable version of easyp.","content":"Go install It will install the latest stable version of easyp."},{"id":"introduction/install::build-from-source::6","title":"Install the EasyP cli","section":"Build from source","path":"/docs/guide/introduction/install#build-from-source","headings":["Build from source"],"excerpt":"Build from source Clone repository","content":"Build from source Clone repository"},{"id":"introduction/install::build-from-source::7","title":"Install the EasyP cli","section":"Build from source","path":"/docs/guide/introduction/install#build-from-source","headings":["Build from source"],"excerpt":"Build from source Build by golang","content":"Build from source Build by golang"},{"id":"introduction/quickstart::top::0","title":"Quickstart","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"EasyP is a modern toolkit for working with Protobuf files. In this quickstart, you'll learn to:","content":"EasyP is a modern toolkit for working with Protobuf files. In this quickstart, you'll learn to:"},{"id":"introduction/quickstart::top::1","title":"Quickstart","path":"/docs/guide/introduction/quickstart","headings":[],"excerpt":"**Initialize** your project with EasyP configuration **Set up linting** to catch errors and ensure best practices **Manage dependencies** from Git repositories **Generate code** from your Protobuf files","content":"**Initialize** your project with EasyP configuration **Set up linting** to catch errors and ensure best practices **Manage dependencies** from Git repositories **Generate code** from your Protobuf files"},{"id":"introduction/quickstart::prerequisites::2","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites Before you begin, make sure you have:","content":"Prerequisites Before you begin, make sure you have:"},{"id":"introduction/quickstart::prerequisites::3","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites **EasyP CLI installed** - See Installation guide if you haven't already **Git** installed and in your $PATH **Protobuf files** ready to work with (or create some as you go)","content":"Prerequisites **EasyP CLI installed** - See Installation guide if you haven't already **Git** installed and in your $PATH **Protobuf files** ready to work with (or create some as you go)"},{"id":"introduction/quickstart::prerequisites::4","title":"Quickstart","section":"Prerequisites","path":"/docs/guide/introduction/quickstart#prerequisites","headings":["Prerequisites"],"excerpt":"Prerequisites You can verify your installation:","content":"Prerequisites You can verify your installation:"},{"id":"introduction/quickstart::initialize-your-project::5","title":"Quickstart","section":"Initialize your project","path":"/docs/guide/introduction/quickstart#initialize-your-project","headings":["Initialize your project"],"excerpt":"Initialize your project Start by creating an easyp.yaml configuration file in your project root:","content":"Initialize your project Start by creating an easyp.yaml configuration file in your project root:"},{"id":"introduction/quickstart::initialize-your-project::6","title":"Quickstart","section":"Initialize your project","path":"/docs/guide/introduction/quickstart#initialize-your-project","headings":["Initialize your project"],"excerpt":"Initialize your project This command generates a commented template with default lint and breaking settings. easyp init is interactive: if buf.yml/buf.yaml exists in the target root, EasyP asks whether to migrate it; if ","content":"Initialize your project This command generates a commented template with default lint and breaking settings. easyp init is interactive: if buf.yml/buf.yaml exists in the target root, EasyP asks whether to migrate it; if easyp.yaml already exists, it asks before overwriting."},{"id":"introduction/quickstart::configure-linting::7","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting Linting helps catch errors and ensures your Protobuf files follow best practices. EasyP provides default rules compatible with Buf standards.","content":"Configure linting Linting helps catch errors and ensures your Protobuf files follow best practices. EasyP provides default rules compatible with Buf standards."},{"id":"introduction/quickstart::configure-linting::8","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting easyp init already generates a lint section. Adjust it if needed, for example:","content":"Configure linting easyp init already generates a lint section. Adjust it if needed, for example:"},{"id":"introduction/quickstart::configure-linting::9","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting Now you can run the linter:","content":"Configure linting Now you can run the linter:"},{"id":"introduction/quickstart::configure-linting::10","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting The linter will check all your .proto files and report any issues found.","content":"Configure linting The linter will check all your .proto files and report any issues found."},{"id":"introduction/quickstart::configure-linting::11","title":"Quickstart","section":"Configure linting","path":"/docs/guide/introduction/quickstart#configure-linting","headings":["Configure linting"],"excerpt":"Configure linting ::: tip EasyP's linting rules are 100% compatible with Buf, making migration easy if you're switching tools. :::","content":"Configure linting ::: tip EasyP's linting rules are 100% compatible with Buf, making migration easy if you're switching tools. :::"},{"id":"introduction/quickstart::manage-dependencies::12","title":"Quickstart","section":"Manage dependencies","path":"/docs/guide/introduction/quickstart#manage-dependencies","headings":["Manage dependencies"],"excerpt":"Manage dependencies If your project uses third-party Protobuf packages (like Google APIs or gRPC Gateway), EasyP makes it easy to manage them.","content":"Manage dependencies If your project uses third-party Protobuf packages (like Google APIs or gRPC Gateway), EasyP makes it easy to manage them."},{"id":"introduction/quickstart::dependency-format::13","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format Dependencies use a simple format: $GIT_LINK@$VERSION","content":"Dependency format Dependencies use a simple format: $GIT_LINK@$VERSION"},{"id":"introduction/quickstart::dependency-format::14","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format **$GIT_LINK** - URL to any Git repository (GitHub, GitLab, etc.) **$VERSION** - Git tag or commit hash (optional)","content":"Dependency format **$GIT_LINK** - URL to any Git repository (GitHub, GitLab, etc.) **$VERSION** - Git tag or commit hash (optional)"},{"id":"introduction/quickstart::dependency-format::15","title":"Quickstart","section":"Dependency format","path":"/docs/guide/introduction/quickstart#dependency-format","headings":["Dependency format"],"excerpt":"Dependency format If you omit the version, EasyP downloads the latest commit from the default branch.","content":"Dependency format If you omit the version, EasyP downloads the latest commit from the default branch."},{"id":"introduction/quickstart::add-dependencies::16","title":"Quickstart","section":"Add dependencies","path":"/docs/guide/introduction/quickstart#add-dependencies","headings":["Add dependencies"],"excerpt":"Add dependencies Update your easyp.yaml to include dependencies:","content":"Add dependencies Update your easyp.yaml to include dependencies:"},{"id":"introduction/quickstart::download-dependencies::17","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies Download the packages you specified:","content":"Download dependencies Download the packages you specified:"},{"id":"introduction/quickstart::download-dependencies::18","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies This command: Downloads dependencies from easyp.lock if it exists Otherwise, downloads from easyp.yaml and creates easyp.lock","content":"Download dependencies This command: Downloads dependencies from easyp.lock if it exists Otherwise, downloads from easyp.yaml and creates easyp.lock"},{"id":"introduction/quickstart::download-dependencies::19","title":"Quickstart","section":"Download dependencies","path":"/docs/guide/introduction/quickstart#download-dependencies","headings":["Download dependencies"],"excerpt":"Download dependencies ::: info **Tip:** Use easyp mod update to ignore the lock file and fetch the latest versions from easyp.yaml. :::","content":"Download dependencies ::: info **Tip:** Use easyp mod update to ignore the lock file and fetch the latest versions from easyp.yaml. :::"},{"id":"introduction/quickstart::generate-code::20","title":"Quickstart","section":"Generate code","path":"/docs/guide/introduction/quickstart#generate-code","headings":["Generate code"],"excerpt":"Generate code Now let's configure code generation. EasyP supports all standard Protobuf plugins.","content":"Generate code Now let's configure code generation. EasyP supports all standard Protobuf plugins."},{"id":"introduction/quickstart::configure-generation::21","title":"Quickstart","section":"Configure generation","path":"/docs/guide/introduction/quickstart#configure-generation","headings":["Configure generation"],"excerpt":"Configure generation Add plugin configuration to your easyp.yaml:","content":"Configure generation Add plugin configuration to your easyp.yaml:"},{"id":"introduction/quickstart::run-code-generation::22","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation Generate your code stubs:","content":"Run code generation Generate your code stubs:"},{"id":"introduction/quickstart::run-code-generation::23","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation EasyP will: Resolve all dependencies Connect to the EasyP service (or run locally) Execute the configured plugins Output generated code to the specified directories","content":"Run code generation EasyP will: Resolve all dependencies Connect to the EasyP service (or run locally) Execute the configured plugins Output generated code to the specified directories"},{"id":"introduction/quickstart::run-code-generation::24","title":"Quickstart","section":"Run code generation","path":"/docs/guide/introduction/quickstart#run-code-generation","headings":["Run code generation"],"excerpt":"Run code generation ::: tip EasyP uses a hybrid runtime with WASM for speed and Docker for heavy plugins, giving you the best of both worlds. :::","content":"Run code generation ::: tip EasyP uses a hybrid runtime with WASM for speed and Docker for heavy plugins, giving you the best of both worlds. :::"},{"id":"introduction/quickstart::next-steps::25","title":"Quickstart","section":"Next steps","path":"/docs/guide/introduction/quickstart#next-steps","headings":["Next steps"],"excerpt":"Next steps Congratulations! 🎉 You've successfully: ✅ Initialized an EasyP project ✅ Configured linting rules ✅ Managed third-party dependencies ✅ Generated code from your Protobuf files","content":"Next steps Congratulations! 🎉 You've successfully: ✅ Initialized an EasyP project ✅ Configured linting rules ✅ Managed third-party dependencies ✅ Generated code from your Protobuf files"},{"id":"introduction/quickstart::learn-more::26","title":"Quickstart","section":"Learn more","path":"/docs/guide/introduction/quickstart#learn-more","headings":["Learn more"],"excerpt":"Learn more **CLI Reference** - Deep dive into all CLI commands **API Service** - Set up remote code generation **Configuration** - Explore all configuration options","content":"Learn more **CLI Reference** - Deep dive into all CLI commands **API Service** - Set up remote code generation **Configuration** - Explore all configuration options"},{"id":"introduction/quickstart::learn-more::27","title":"Quickstart","section":"Learn more","path":"/docs/guide/introduction/quickstart#learn-more","headings":["Learn more"],"excerpt":"Learn more *Enjoy working with Protobuf without any pain! 🚀*","content":"Learn more *Enjoy working with Protobuf without any pain! 🚀*"},{"id":"introduction/what-is::top::0","title":"What is EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"EasyP is a modern Protocol Buffers toolkit that consolidates your entire protobuf workflow into a single, powerful CLI tool. It combines linting, package management, code generation, and compatibility checking in a unifi","content":"EasyP is a modern Protocol Buffers toolkit that consolidates your entire protobuf workflow into a single, powerful CLI tool. It combines linting, package management, code generation, and compatibility checking in a unified interface designed to eliminate the complexity of traditional protobuf development."},{"id":"introduction/what-is::top::1","title":"What is EasyP?","path":"/docs/guide/introduction/what-is","headings":[],"excerpt":"Just want to try it out? Skip to the Quickstart.","content":"Just want to try it out? Skip to the Quickstart."},{"id":"introduction/what-is::the-problem-fragmented-proto-workflows::2","title":"What is EasyP?","section":"The Problem: Fragmented Proto Workflows","path":"/docs/guide/introduction/what-is#the-problem-fragmented-proto-workflows","headings":["The Problem: Fragmented Proto Workflows"],"excerpt":"The Problem: Fragmented Proto Workflows Working with Protocol Buffers across projects creates unnecessary complexity and friction:","content":"The Problem: Fragmented Proto Workflows Working with Protocol Buffers across projects creates unnecessary complexity and friction:"},{"id":"introduction/what-is::tool-chaos::3","title":"What is EasyP?","section":"Tool Chaos","path":"/docs/guide/introduction/what-is#tool-chaos","headings":["Tool Chaos"],"excerpt":"Tool Chaos **Multiple tools for different tasks**: Separate tools for linting, generation, and dependency management **Inconsistent configurations**: Different config formats across projects and teams **Complex setup**: ","content":"Tool Chaos **Multiple tools for different tasks**: Separate tools for linting, generation, and dependency management **Inconsistent configurations**: Different config formats across projects and teams **Complex setup**: Time-consuming onboarding for new developers joining projects"},{"id":"introduction/what-is::dependency-management-issues::4","title":"What is EasyP?","section":"Dependency Management Issues","path":"/docs/guide/introduction/what-is#dependency-management-issues","headings":["Dependency Management Issues"],"excerpt":"Dependency Management Issues **No standardized approach**: Each project handles proto dependencies differently **Version conflicts**: Difficult to resolve conflicts between different proto libraries **Build reproducibili","content":"Dependency Management Issues **No standardized approach**: Each project handles proto dependencies differently **Version conflicts**: Difficult to resolve conflicts between different proto libraries **Build reproducibility**: Hard to ensure consistent builds across environments"},{"id":"introduction/what-is::development-friction::5","title":"What is EasyP?","section":"Development Friction","path":"/docs/guide/introduction/what-is#development-friction","headings":["Development Friction"],"excerpt":"Development Friction **Manual processes**: Repetitive workflows for common proto tasks **Configuration sprawl**: Multiple config files with different formats **Time-consuming compatibility checks**: Manual verification o","content":"Development Friction **Manual processes**: Repetitive workflows for common proto tasks **Configuration sprawl**: Multiple config files with different formats **Time-consuming compatibility checks**: Manual verification of API changes"},{"id":"introduction/what-is::the-solution-unified-proto-toolkit::6","title":"What is EasyP?","section":"The Solution: Unified Proto Toolkit","path":"/docs/guide/introduction/what-is#the-solution-unified-proto-toolkit","headings":["The Solution: Unified Proto Toolkit"],"excerpt":"The Solution: Unified Proto Toolkit EasyP addresses these challenges by providing a comprehensive, opinionated toolkit that standardizes protobuf workflows:","content":"The Solution: Unified Proto Toolkit EasyP addresses these challenges by providing a comprehensive, opinionated toolkit that standardizes protobuf workflows:"},{"id":"introduction/what-is::one-tool-all-tasks::7","title":"What is EasyP?","section":"One Tool, All Tasks","path":"/docs/guide/introduction/what-is#one-tool-all-tasks","headings":["One Tool, All Tasks"],"excerpt":"One Tool, All Tasks Instead of juggling multiple tools, EasyP provides everything you need: **Linting** with comprehensive rule sets **Package management** with Git-native dependencies **Code generation** with local and ","content":"One Tool, All Tasks Instead of juggling multiple tools, EasyP provides everything you need: **Linting** with comprehensive rule sets **Package management** with Git-native dependencies **Code generation** with local and remote plugin support **Breaking change detection** for API compatibility"},{"id":"introduction/what-is::standardized-configuration::8","title":"What is EasyP?","section":"Standardized Configuration","path":"/docs/guide/introduction/what-is#standardized-configuration","headings":["Standardized Configuration"],"excerpt":"Standardized Configuration A single easyp.yaml file configures your entire protobuf workflow, eliminating configuration sprawl and ensuring consistency across projects.","content":"Standardized Configuration A single easyp.yaml file configures your entire protobuf workflow, eliminating configuration sprawl and ensuring consistency across projects."},{"id":"introduction/what-is::git-native-dependencies::9","title":"What is EasyP?","section":"Git-Native Dependencies","path":"/docs/guide/introduction/what-is#git-native-dependencies","headings":["Git-Native Dependencies"],"excerpt":"Git-Native Dependencies Direct integration with Git repositories for proto dependencies eliminates the need for centralized registries while providing version control and reproducibility.","content":"Git-Native Dependencies Direct integration with Git repositories for proto dependencies eliminates the need for centralized registries while providing version control and reproducibility."},{"id":"introduction/what-is::key-features::10","title":"What is EasyP?","section":"Key Features","path":"/docs/guide/introduction/what-is#key-features","headings":["Key Features"],"excerpt":"Key Features Feature Description --------- ------------- 🔍 **Comprehensive Linting** Built-in support for buf's linting rules with customizable configurations to enforce API design best practices. 📦 **Smart Package Man","content":"Key Features Feature Description --------- ------------- 🔍 **Comprehensive Linting** Built-in support for buf's linting rules with customizable configurations to enforce API design best practices. 📦 **Smart Package Manager** Git-based dependency management with lock file support for reproducible builds across environments. ⚡ **Code Generation** Multi-language code generation with support for both local protoc plugins and remote plugin execution. 🔄 **Breaking Change Detection** Automated API compatibility verification against Git branches to prevent accidental breaking changes. 🌐 **Remote Plugin Support** Execute plugins via centralized EasyP API service for consistent, isolated execution without local dependencies. 🎯 **Developer Experience** Auto-completion, intuitive commands, clear error messages, and comprehensive documentation."},{"id":"introduction/what-is::supported-plugin-types::11","title":"What is EasyP?","section":"Supported Plugin Types","path":"/docs/guide/introduction/what-is#supported-plugin-types","headings":["Supported Plugin Types"],"excerpt":"Supported Plugin Types EasyP provides flexibility in how you execute code generation plugins:","content":"Supported Plugin Types EasyP provides flexibility in how you execute code generation plugins:"},{"id":"introduction/what-is::local-plugins::12","title":"What is EasyP?","section":"Local Plugins","path":"/docs/guide/introduction/what-is#local-plugins","headings":["Local Plugins"],"excerpt":"Local Plugins Standard protoc plugins installed on your system:","content":"Local Plugins Standard protoc plugins installed on your system:"},{"id":"introduction/what-is::remote-plugins::13","title":"What is EasyP?","section":"Remote Plugins","path":"/docs/guide/introduction/what-is#remote-plugins","headings":["Remote Plugins"],"excerpt":"Remote Plugins Plugins executed via EasyP API service for consistent results:","content":"Remote Plugins Plugins executed via EasyP API service for consistent results:"},{"id":"introduction/what-is::custom-plugins::14","title":"What is EasyP?","section":"Custom Plugins","path":"/docs/guide/introduction/what-is#custom-plugins","headings":["Custom Plugins"],"excerpt":"Custom Plugins Support for custom plugin development and distribution through the ecosystem.","content":"Custom Plugins Support for custom plugin development and distribution through the ecosystem."},{"id":"introduction/what-is::decentralized-package-management::15","title":"What is EasyP?","section":"Decentralized Package Management","path":"/docs/guide/introduction/what-is#decentralized-package-management","headings":["Decentralized Package Management"],"excerpt":"Decentralized Package Management Unlike other tools, EasyP doesn't rely on a centralized server for package distribution. Instead, any Git repository can serve as a package source, giving you:","content":"Decentralized Package Management Unlike other tools, EasyP doesn't rely on a centralized server for package distribution. Instead, any Git repository can serve as a package source, giving you:"},{"id":"introduction/what-is::decentralized-package-management::16","title":"What is EasyP?","section":"Decentralized Package Management","path":"/docs/guide/introduction/what-is#decentralized-package-management","headings":["Decentralized Package Management"],"excerpt":"Decentralized Package Management **Flexibility and Control**: Use any Git hosting service (GitHub, GitLab, self-hosted) **No Vendor Lock-in**: Your dependencies aren't tied to a specific registry **Version Control**: Ful","content":"Decentralized Package Management **Flexibility and Control**: Use any Git hosting service (GitHub, GitLab, self-hosted) **No Vendor Lock-in**: Your dependencies aren't tied to a specific registry **Version Control**: Full Git history and branching for your proto dependencies **Enterprise-Friendly**: Works with private repositories and corporate Git infrastructure"},{"id":"introduction/what-is::seamless-migration-from-buf::17","title":"What is EasyP?","section":"Seamless Migration from Buf","path":"/docs/guide/introduction/what-is#seamless-migration-from-buf","headings":["Seamless Migration from Buf"],"excerpt":"Seamless Migration from Buf EasyP is designed with buf compatibility in mind:","content":"Seamless Migration from Buf EasyP is designed with buf compatibility in mind:"},{"id":"introduction/what-is::seamless-migration-from-buf::18","title":"What is EasyP?","section":"Seamless Migration from Buf","path":"/docs/guide/introduction/what-is#seamless-migration-from-buf","headings":["Seamless Migration from Buf"],"excerpt":"Seamless Migration from Buf **Compatible rule sets**: Uses the same linting rules as buf **Familiar configuration**: Similar YAML structure with enhanced features **Drop-in replacement**: Can often replace buf with minim","content":"Seamless Migration from Buf **Compatible rule sets**: Uses the same linting rules as buf **Familiar configuration**: Similar YAML structure with enhanced features **Drop-in replacement**: Can often replace buf with minimal configuration changes **Gradual migration**: Adopt EasyP features incrementally without disrupting existing workflows"},{"id":"introduction/what-is::easyp-vs-bufbuild-comparison::19","title":"What is EasyP?","section":"EasyP vs buf.build Comparison","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild-comparison","headings":["EasyP vs buf.build Comparison"],"excerpt":"EasyP vs buf.build Comparison Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git-based repositories Buf Schema Registry (BSR) **Vendor Lock-in** None - works with any Git hosting Tied to","content":"EasyP vs buf.build Comparison Feature EasyP buf.build --------- -------- ----------- **Dependency Management** Git-based repositories Buf Schema Registry (BSR) **Vendor Lock-in** None - works with any Git hosting Tied to BSR for full features **Plugin Execution** Local + Remote plugins Local + BSR plugins **Private Dependencies** Any Git provider (GitHub, GitLab, etc.) BSR or manual management **Offline Development** Full support with mod vendor Limited without BSR access **Enterprise Integration** Works with existing Git infrastructure Requires BSR setup **Breaking Change Detection** Against any Git reference Against any Git reference **Package Distribution** Any Git repository BSR required for publishing **License** Apache 2.0 Apache 2.0 **Community** Growing Established"},{"id":"introduction/what-is::easyp-vs-bufbuild-comparison::20","title":"What is EasyP?","section":"EasyP vs buf.build Comparison","path":"/docs/guide/introduction/what-is#easyp-vs-bufbuild-comparison","headings":["EasyP vs buf.build Comparison"],"excerpt":"EasyP vs buf.build Comparison **Migration Benefits:** **No infrastructure changes**: Continue using your existing Git repositories **Gradual adoption**: Start with EasyP while keeping existing buf configurations **Enhanc","content":"EasyP vs buf.build Comparison **Migration Benefits:** **No infrastructure changes**: Continue using your existing Git repositories **Gradual adoption**: Start with EasyP while keeping existing buf configurations **Enhanced flexibility**: Access to both local and remote plugin execution **Simplified workflows**: Single configuration file for all protobuf operations"},{"id":"introduction/what-is::our-goals-for-protobuf::21","title":"What is EasyP?","section":"Our Goals for Protobuf","path":"/docs/guide/introduction/what-is#our-goals-for-protobuf","headings":["Our Goals for Protobuf"],"excerpt":"Our Goals for Protobuf EasyP's mission is to accelerate the adoption of **schema-driven API development** by making Protocol Buffers more accessible and reliable:","content":"Our Goals for Protobuf EasyP's mission is to accelerate the adoption of **schema-driven API development** by making Protocol Buffers more accessible and reliable:"},{"id":"introduction/what-is::modern-protobuf-ecosystem::22","title":"What is EasyP?","section":"Modern Protobuf Ecosystem","path":"/docs/guide/introduction/what-is#modern-protobuf-ecosystem","headings":["Modern Protobuf Ecosystem"],"excerpt":"Modern Protobuf Ecosystem We're building on Protobuf's proven foundation to create a modern development experience that rivals the simplicity of REST/JSON while providing superior type safety and performance.","content":"Modern Protobuf Ecosystem We're building on Protobuf's proven foundation to create a modern development experience that rivals the simplicity of REST/JSON while providing superior type safety and performance."},{"id":"introduction/what-is::developer-experience-first::23","title":"What is EasyP?","section":"Developer Experience First","path":"/docs/guide/introduction/what-is#developer-experience-first","headings":["Developer Experience First"],"excerpt":"Developer Experience First Every feature is designed with developer productivity in mind, from intuitive CLI commands to comprehensive error messages and documentation.","content":"Developer Experience First Every feature is designed with developer productivity in mind, from intuitive CLI commands to comprehensive error messages and documentation."},{"id":"introduction/what-is::enterprise-ready::24","title":"What is EasyP?","section":"Enterprise Ready","path":"/docs/guide/introduction/what-is#enterprise-ready","headings":["Enterprise Ready"],"excerpt":"Enterprise Ready Built for teams and organizations with features like reproducible builds, private repository support, and comprehensive CI/CD integration.","content":"Enterprise Ready Built for teams and organizations with features like reproducible builds, private repository support, and comprehensive CI/CD integration."},{"id":"introduction/what-is::for-individual-developers::25","title":"What is EasyP?","section":"For Individual Developers","path":"/docs/guide/introduction/what-is#for-individual-developers","headings":["For Individual Developers"],"excerpt":"For Individual Developers **Quick Setup**: Get started with protobuf projects in minutes, not hours **Unified Workflow**: One tool for all your protobuf needs **Clear Documentation**: Comprehensive guides and examples","content":"For Individual Developers **Quick Setup**: Get started with protobuf projects in minutes, not hours **Unified Workflow**: One tool for all your protobuf needs **Clear Documentation**: Comprehensive guides and examples"},{"id":"introduction/what-is::for-teams::26","title":"What is EasyP?","section":"For Teams","path":"/docs/guide/introduction/what-is#for-teams","headings":["For Teams"],"excerpt":"For Teams **Consistent Standards**: Enforced linting rules and formatting across all projects **Reproducible Builds**: Lock files ensure everyone builds the same way **Easy Onboarding**: New team members can be productiv","content":"For Teams **Consistent Standards**: Enforced linting rules and formatting across all projects **Reproducible Builds**: Lock files ensure everyone builds the same way **Easy Onboarding**: New team members can be productive immediately"},{"id":"introduction/what-is::for-organizations::27","title":"What is EasyP?","section":"For Organizations","path":"/docs/guide/introduction/what-is#for-organizations","headings":["For Organizations"],"excerpt":"For Organizations **No Vendor Lock-in**: Git-based dependencies work with your existing infrastructure **Enterprise Security**: Support for private repositories and custom authentication **CI/CD Ready**: Designed for aut","content":"For Organizations **No Vendor Lock-in**: Git-based dependencies work with your existing infrastructure **Enterprise Security**: Support for private repositories and custom authentication **CI/CD Ready**: Designed for automated workflows and continuous integration"},{"id":"introduction/what-is::whats-next::28","title":"What is EasyP?","section":"What's Next?","path":"/docs/guide/introduction/what-is#whats-next","headings":["What's Next?"],"excerpt":"What's Next? EasyP simplifies protobuf development so you can focus on building great APIs instead of managing toolchain complexity. Whether you're starting a new project or migrating from existing tools, EasyP provides ","content":"What's Next? EasyP simplifies protobuf development so you can focus on building great APIs instead of managing toolchain complexity. Whether you're starting a new project or migrating from existing tools, EasyP provides a smooth path to modern protobuf development."},{"id":"introduction/what-is::whats-next::29","title":"What is EasyP?","section":"What's Next?","path":"/docs/guide/introduction/what-is#whats-next","headings":["What's Next?"],"excerpt":"What's Next? Ready to get started? Check out our Installation Guide and Quickstart Tutorial.","content":"What's Next? Ready to get started? Check out our Installation Guide and Quickstart Tutorial."},{"id":"introduction/what-is::stargazers-over-time::30","title":"What is EasyP?","section":"Stargazers over time","path":"/docs/guide/introduction/what-is#stargazers-over-time","headings":["Stargazers over time"],"excerpt":"Stargazers over time Stargazers over time","content":"Stargazers over time Stargazers over time"},{"id":"migration/buf-cli::top::0","title":"Buf CLI","path":"/docs/guide/migration/buf-cli","headings":[],"excerpt":"Buf CLI Work in progress","content":"Buf CLI Work in progress"},{"id":"migration/protoc::top::0","title":"Protoc","path":"/docs/guide/migration/protoc","headings":[],"excerpt":"Protoc Work in progress","content":"Protoc Work in progress"},{"id":"migration/protolock::top::0","title":"Protolock","path":"/docs/guide/migration/protolock","headings":[],"excerpt":"Protolock Work in progress","content":"Protolock Work in progress"},{"id":"migration/prototool::top::0","title":"Prototool","path":"/docs/guide/migration/prototool","headings":[],"excerpt":"Prototool Work in progress","content":"Prototool Work in progress"}] \ No newline at end of file diff --git a/example.easyp.yaml b/example.easyp.yaml index 9f3a0e75..9975f688 100644 --- a/example.easyp.yaml +++ b/example.easyp.yaml @@ -18,6 +18,8 @@ breaking: ignore: - some_dir against_git_ref: master + use: + - FILE generate: inputs: diff --git a/internal/api/temporaly_helper.go b/internal/api/temporaly_helper.go index b61f059a..f7c2847e 100644 --- a/internal/api/temporaly_helper.go +++ b/internal/api/temporaly_helper.go @@ -7,6 +7,7 @@ import ( "log/slog" "os" "path/filepath" + "slices" "strings" "github.com/samber/lo" @@ -95,9 +96,12 @@ func buildCore(_ context.Context, log logger.Logger, cfg config.Config, dirWalke linterIgnoreDirs := append(cfg.Lint.Ignore, vendorPath) breakingCheckIgnoreDirs := append(cfg.BreakingCheck.Ignore, vendorPath) + filesCheck := slices.Contains(cfg.BreakingCheck.Use, core.BreakingCheckFilesCheck) + breakingCheckConfig := core.BreakingCheckConfig{ IgnoreDirs: breakingCheckIgnoreDirs, AgainstGitRef: cfg.BreakingCheck.AgainstGitRef, + FilesCheck: filesCheck, } // Convert managed mode configuration diff --git a/internal/config/breaking_check.go b/internal/config/breaking_check.go index 46f8fbd7..13bc3fb2 100644 --- a/internal/config/breaking_check.go +++ b/internal/config/breaking_check.go @@ -4,5 +4,6 @@ package config type BreakingCheck struct { Ignore []string `json:"ignore,omitempty" yaml:"ignore,omitempty"` // git ref to compare with - AgainstGitRef string `json:"against_git_ref,omitempty" yaml:"against_git_ref,omitempty"` + AgainstGitRef string `json:"against_git_ref,omitempty" yaml:"against_git_ref,omitempty"` + Use []string `json:"use,omitempty" yaml:"use,omitempty"` } diff --git a/internal/core/breaking_check.go b/internal/core/breaking_check.go index ac6242fb..061d037f 100644 --- a/internal/core/breaking_check.go +++ b/internal/core/breaking_check.go @@ -15,11 +15,17 @@ import ( var ErrRootOutsideProject = fmt.Errorf("breaking check root must be inside the git repository") +const ( + BreakingCheckFilesCheck string = "FILE" +) + type BreakingCheckConfig struct { // branch name to compare with AgainstGitRef string // dirs should be ignored IgnoreDirs []string + + FilesCheck bool } func (c *Core) BreakingCheck(ctx context.Context, projectRoot, workingDir, path string) ([]IssueInfo, error) { @@ -68,6 +74,8 @@ func (c *Core) BreakingCheck(ctx context.Context, projectRoot, workingDir, path breakingChecker := &BreakingChecker{ against: againstProtoData, current: currentProtoData, + + filesCheck: c.breakingCheckConfig.FilesCheck, } return breakingChecker.Check() diff --git a/internal/core/breaking_checker.go b/internal/core/breaking_checker.go index c0c753e5..40275810 100644 --- a/internal/core/breaking_checker.go +++ b/internal/core/breaking_checker.go @@ -12,6 +12,8 @@ const breakingCheckRuleName = "BREAKING_CHECK" type BreakingChecker struct { against ProtoData current ProtoData + + filesCheck bool } func (b *BreakingChecker) Check() ([]IssueInfo, error) { @@ -86,6 +88,11 @@ func (b *BreakingChecker) checkService(againstService Service) []IssueInfo { return res } + if b.hasFilesCheckError(currentService.ProtoFilePath, againstService.ProtoFilePath) { + issue := getServiceMovedIssue(currentService, againstService) + res = append(res, issue) + } + // check RPCs for _, againstRPC := range againstService.ServiceBody.RPCs { // rpc was deleted @@ -142,6 +149,11 @@ func (b *BreakingChecker) checkMessage(againstMessage Message) []IssueInfo { return res } + if b.hasFilesCheckError(currentMessage.ProtoFilePath, againstMessage.ProtoFilePath) { + issue := getMessageMovedIssue(currentMessage, againstMessage) + res = append(res, issue) + } + // check fields for _, againstField := range againstMessage.MessageBody.Fields { currentField, ok := searchField(currentMessage.MessageBody.Fields, againstField.FieldNumber) @@ -182,6 +194,11 @@ func (b *BreakingChecker) checkOneOf(againstOneOf OneOf) []IssueInfo { return res } + if b.hasFilesCheckError(currentOneOf.ProtoFilePath, againstOneOf.ProtoFilePath) { + issue := getOneOfMovedIssue(currentOneOf, againstOneOf) + res = append(res, issue) + } + // check fields for _, againstField := range againstOneOf.OneofFields { currentField, ok := searchOneOfField(currentOneOf.OneofFields, againstField.FieldNumber) @@ -213,6 +230,11 @@ func (b *BreakingChecker) checkEnum(againstEnum Enum) []IssueInfo { return res } + if b.hasFilesCheckError(currentEnum.ProtoFilePath, againstEnum.ProtoFilePath) { + issue := getEnumMovedIssue(currentEnum, againstEnum) + res = append(res, issue) + } + for _, againstField := range againstEnum.EnumBody.EnumFields { currentField, ok := searchEnumField(currentEnum.EnumBody.EnumFields, againstField.Number) if !ok { @@ -233,6 +255,14 @@ func (b *BreakingChecker) checkEnum(againstEnum Enum) []IssueInfo { // ===== utils ===== +func (b *BreakingChecker) hasFilesCheckError(path1, path2 string) bool { + if b.filesCheck && path1 != path2 { + return true + } + + return false +} + func getImport(source ProtoData, packageName PackageName, importPath ImportPath) (Import, bool) { collection, ok := source[packageName] if !ok { @@ -407,6 +437,46 @@ func getMessageDeletedIssue(againstMessage Message) IssueInfo { return buildBreakingCheckIssue(againstMessage.ProtoFilePath, message, againstMessage.Meta.Pos) } +func getMessageMovedIssue(currentMessage, againstMessage Message) IssueInfo { + message := fmt.Sprintf( + "Previously present Message \"%s\" was moved from \"%s\" file to \"%s\" file\n", + againstMessage.MessagePath, + againstMessage.ProtoFilePath, + currentMessage.ProtoFilePath, + ) + return buildBreakingCheckIssue(againstMessage.ProtoFilePath, message, againstMessage.Meta.Pos) +} + +func getServiceMovedIssue(currentService, againstService Service) IssueInfo { + message := fmt.Sprintf( + "Previously present Service \"%s\" was moved from \"%s\" file to \"%s\" file\n", + againstService.ServiceName, + againstService.ProtoFilePath, + currentService.ProtoFilePath, + ) + return buildBreakingCheckIssue(againstService.ProtoFilePath, message, againstService.Meta.Pos) +} + +func getOneOfMovedIssue(currentOneOf, againstOneOf OneOf) IssueInfo { + message := fmt.Sprintf( + "Previously present OneOf \"%s\" was moved from \"%s\" file to \"%s\" file\n", + againstOneOf.OneofName, + againstOneOf.ProtoFilePath, + currentOneOf.ProtoFilePath, + ) + return buildBreakingCheckIssue(againstOneOf.ProtoFilePath, message, againstOneOf.Meta.Pos) +} + +func getEnumMovedIssue(currentEnum, againstEnum Enum) IssueInfo { + message := fmt.Sprintf( + "Previously present Enum \"%s\" was moved from \"%s\" file to \"%s\" file\n", + againstEnum.EnumName, + againstEnum.ProtoFilePath, + currentEnum.ProtoFilePath, + ) + return buildBreakingCheckIssue(againstEnum.ProtoFilePath, message, againstEnum.Meta.Pos) +} + func getFieldDeletedIssue(againstMessage Message, againstField *parser.Field) IssueInfo { message := fmt.Sprintf("Previously present field \"%s\" with name \"%s\" "+ "on message \"%s\" was deleted.", diff --git a/schemas/easyp-config-v1.schema.json b/schemas/easyp-config-v1.schema.json index 3733d88f..81128b07 100644 --- a/schemas/easyp-config-v1.schema.json +++ b/schemas/easyp-config-v1.schema.json @@ -352,6 +352,12 @@ }, "against_git_ref": { "type": "string" + }, + "use": { + "items": { + "type": "string" + }, + "type": "array" } }, "additionalProperties": false, diff --git a/schemas/easyp-config.schema.json b/schemas/easyp-config.schema.json index 3733d88f..81128b07 100644 --- a/schemas/easyp-config.schema.json +++ b/schemas/easyp-config.schema.json @@ -352,6 +352,12 @@ }, "against_git_ref": { "type": "string" + }, + "use": { + "items": { + "type": "string" + }, + "type": "array" } }, "additionalProperties": false,